数据结构----堆 和 堆排序 代码

目录

Heap.h

Heap.c

HeapTest.c


Heap.h

#pragma once/*堆*/
//完全二叉树
//可以用数组存,所以实现和数据结构很类似#include <stdio.h>
#include <stdlib.h>
#include <assert.h>/**/
#include <stdbool.h>#define InitSize 100
//#define AddSize 50
//可以直接扩大两倍,不一定固定扩大的个数typedef int HeapElemtype;typedef struct Heap
{HeapElemtype* a;int size;int capacity;
}Hp;void HeapInit(Hp* heap);
void HeapDestroy(Hp* heap);void HeapPush(Hp* heap, HeapElemtype x);
void AdjustUp(HeapElemtype* a,int child);void HeapPop(Hp* heap);
void AdjustDown(HeapElemtype* a, int n, int parent);void Swap(HeapElemtype* a, HeapElemtype* b);bool HeapEmpty(Hp* heap);HeapElemtype HeapTop(Hp* heap);
int HeapSize(Hp* heap);//堆排序
void HeapSort(HeapElemtype* a, int n);

Heap.c

#include "Heap.h"void HeapInit(Hp* heap)
{assert(heap);Hp* temp = (HeapElemtype*)malloc(sizeof(Hp) * InitSize);if (temp == NULL){perror("malloc fail");return;}heap->a = temp;heap->capacity = InitSize;heap->size = 0;
}void HeapDestroy(Hp* heap)
{assert(heap);heap->capacity = 0;heap->size = 0;free(heap->a);heap->a = NULL;
}void HeapPush(Hp* heap, HeapElemtype x)
{Hp* temp;if (heap->size == heap->capacity){//要扩容temp = (Hp*)realloc(heap->a,sizeof(Hp) * (heap->capacity * 2));if (temp == NULL){perror("realloc fail");return;}		heap->a = temp;heap->capacity *= 2;}//插入heap->a[heap->size] = x;heap->size++;//向上调整!!!!!!!!/*插入:向上调整*/AdjustUp(heap->a, heap->size - 1);
}//小根堆:只要插入的数据比父亲小,就升辈分
//大                         大//传参为数组的向上调整代码
void AdjustUp(HeapElemtype* a, int child)
{HeapElemtype temp = a[child];int parent = (child - 1) / 2;//循环上移,直到合适位置//也可以写成:while (child >= 0),注意:不是while (parent >= 0),因为最坏的情况是孩子走到根节点,而不是父亲走到根节点//但该种写法的while 内部要写为:if (heap->a[child] < heap->a[parent])交换;else break;while (a[child] < a[parent]){//调整数组元素Swap(&a[child], &a[parent]);//更新下标,方便后续继续调整child = parent;parent = (child - 1) / 2;}
}void Swap(HeapElemtype* a, HeapElemtype* b)
{HeapElemtype temp = *a;*a = *b;*b = temp;
}//注意堆中删除数一般为删除堆顶数据,因为删除堆的最后一个没有意义
//删除数据:先交换首尾数据,再将根和最小的孩子比较,如果根 < 最小的孩子----->不动;否则,向下调整/*删除:向下调整*/
void HeapPop(Hp* heap)
{assert(heap);assert(heap->size);//交换首尾数据Swap(&heap->a[0], &heap->a[heap->size - 1]);heap->size--;//向下调整AdjustDown(heap->a, heap->size, 0);/*注意,并不是所有情况都是删堆顶,所以要传入一个parent参数*/
}//返回堆顶
HeapElemtype HeapTop(Hp* heap)
{assert(heap);assert(heap->size);return heap->a[0];
}//传参为数组的向下调整代码
void AdjustDown(HeapElemtype* a, int n, int parent)
{int childl = parent * 2 + 1, childr = parent * 2 + 2;int child = a[childl] < a[childr] ? childl : childr;//也可写成:child + 1 < heap->size && a[child + 1] < a[child]  child++;while (child < n/*不仅要注意这个条件,同时要注意要写在前面*/ && a[parent] > a[child]){Swap(&a[parent], &a[child]);parent = child;childl = parent * 2 + 1, childr = parent * 2 + 2;child = a[childl] < a[childr] ? childl : childr;}
}bool HeapEmpty(Hp* heap)
{assert(heap);return heap->size == 0;
}int HeapSize(Hp* heap)
{assert(heap);return heap->size;
}//堆排序:不要建堆,只是要用到里面的向上调整,所以传参不要传堆,而是传数组------节省建堆的空间和拷贝数据的消耗
// 堆只是一个数据结构,而不是一个排序方法,排序只是单独的把其向上调整的地方分离出来,使得只用调整数组,不去建堆
// 这也是为什么向上调整AdjustUp和向下调整AdjustDown部分传参不是传堆的地址,而是传数组地址的原因
//void HeapSort(Hp* heap)
//小堆:排降序	大堆:排升序------升降序看的是最后数组的顺序
void HeapSort(HeapElemtype* a, int n)
{//建堆--向上调整建堆//for (int i = 1; i < n; i++)//{//	AdjustUp(a, i);//}//向下调整建堆//因为一个向上调整,一个向下调整很麻烦,所以把向上调整的部分可换为向下调整//要确保每个孩子是堆,所以从下往上调整,又因为叶子节点就是堆,所以要找最后一个非叶子节点//也就是从最后一个叶子的父节点开始调整for (int i = ((n - 1/*最后一个叶子的下标*/) - 1) / 2/*最后一个孩子的父亲*/; i >= 0; i--){AdjustDown(a, n, i);}//输出:输出队首,然后向下调整------先交换首尾,再size--,再向下调整int size = n;while (size){Swap(&a[0], &a[size - 1]);size--;AdjustDown(a, size, 0);}
}

HeapTest.c

参考代码,具体的请自行更改使用

										/*堆*/#include "Heap.h"void HeapPrint(Hp* heap)
{//按照直接通过数组打印------满足堆的形态,但不是有序的,因为不是输出堆顶元素(堆顶元素一定是该堆的最值)//for (int i = 0; i < heap->size; i++)//{//	printf("%d ", heap->a[i]);//}//printf("\n");//按照Pop打印//while (!HeapEmpty(&heap))不能传地址,已经是指针了while (!HeapEmpty(heap)){//不能传地址,已经是地址printf("%d ", HeapTop(heap));//不能传地址,已经是地址HeapPop(heap);}printf("\n");
}void test01()
{Hp heap;HeapInit(&heap);HeapElemtype a[] = { 10, 15, 56, 25, 30, 70, 0 };for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++){HeapPush(&heap, a[i]);}HeapPrint(&heap);
}void test02()
{Hp heap;HeapInit(&heap);//HeapElemtype a[] = { 10, 15, 56, 25, 30, 70, 0 };HeapElemtype a[] = { 15, 21, 10, 2121, 1002,2 };for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++){HeapPush(&heap, a[i]);}HeapPrint(&heap);HeapPop(&heap);HeapPrint(&heap);printf("堆顶元素为:%d\n", HeapTop(&heap));
}void test03()
{Hp heap;HeapInit(&heap);HeapElemtype a[] = { 15, 21, 10, 2121, 1002,2 };for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++){HeapPush(&heap, a[i]);}HeapPop(&heap);HeapPrint(&heap);
}void test04()
{HeapElemtype a[] = { 15, 21, 10, 2121, 1002, 2 };HeapSort(&a, sizeof(a) / sizeof(a[0]));for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)printf("%d ", a[i]);printf("\n");
}int main()
{//test01();//test02();//test03();test04();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/812802.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】04串

串 1. 定义2. 串的比较3. 串的存储结构4. 具体实现5. 模式匹配5.1 常规思路实现5.2 KMP模式匹配算法5.2.1 next数组计算5.2.1 代码计算next数组5.2.2 KMP算法实现 1. 定义 串(string)是由零个或多个字符组成的有限序列&#xff0c;又叫字符串。 一般记为s a 1 , a 2 , . . . ,…

NGO-VMD+皮尔逊系数+小波阈值降噪+重构

NGO-VMD皮尔逊系数小波阈值降噪重构 NGO-VMD皮尔逊系数小波阈值降噪重构代码获取戳此处代码获取戳此处 以西储大学轴承数据为例&#xff0c;进行VMD&#xff0c;且采用NGO进行K a参数寻优 并对分解分量计算皮尔逊相关系数筛选含噪声分量&#xff0c;对其进行小波软硬阈值降噪&a…

C++计算程序运行时间

引言 有时候我们需要简单计算下程序的运行时间&#xff0c;但又不想借助工具&#xff0c;而是简单的几行代码来粗略计算下时间&#xff0c;话不多说我们直接开始吧。 chrono库使用 C11中可以通过该库来实现&#xff0c;示例代码如下&#xff1a; #include <iostream>…

C/C++内存泄漏及检测

“该死系统存在内存泄漏问题”&#xff0c;项目中由于各方面因素&#xff0c;总是有人抱怨存在内存泄漏&#xff0c;系统长时间运行之后&#xff0c;可用内存越来越少&#xff0c;甚至导致了某些服务失败。内存泄漏是最难发现的常见错误之一&#xff0c;因为除非用完内存或调用…

【JAVA基础篇教学】第十篇:Java中Map详解说明

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第十篇&#xff1a;Java中Map详解说明。 在 Java 编程中&#xff0c;Map 接口代表了一种键值对的集合&#xff0c;每个键对应一个值。Map 接口提供了一系列操作方法&#xff0c;可以方便地对键值对进行增删改查等操作。本…

好题推荐 CF1265E Beautiful Mirrors

题目传送门-洛谷 题目传送门-CF Part.1 题意 有 n n n 面镜子&#xff0c;第 i i i 个镜子有 p i 100 \frac{p_{i}}{100} 100pi​​ 的概率说 “你真好看”。一个人从第一个镜子开始&#xff0c;到第 n n n 个镜子说 “你真好看” 为止的天数期望&#xff0c;方式如下&am…

C++菜单查询

定义一个菜品类&#xff0c;包含菜名和菜价两个私有数据成员&#xff0c;设置菜名菜价&#xff0c;输出菜名菜价&#xff0c;获取菜价等共有成员函数。main函数中读入n个菜品的菜名和价格&#xff0c;然后输出菜价低于mprice的所有菜品信息(按输入顺序输出)&#xff0c;以及低于…

JavaScript:Object对象的属性方法

Object.defineProperty()方法: Object.defineProperty()方法---为对象添加属性---Vue的源码中经常用到 // 1 Object.defineProperty()方法---为对象添加属性---Vue的源码中经常用到const person {firstName: 呼呼,lastName: 憨憨}// // 为某个对象添加一个属性,并对该属性进…

模板方法模式:定义算法骨架的设计策略

在软件开发中&#xff0c;模板方法模式是一种行为型设计模式&#xff0c;它在父类中定义一个操作的算法框架&#xff0c;允许子类在不改变算法结构的情况下重定义算法的某些步骤。这种模式是基于继承的基本原则&#xff0c;通过抽象类达到代码复用的目的。本文将详细介绍模板方…

NASA数据集——亚洲夏季季风化学与气候影响项目超高灵敏度气溶胶光谱(UHSAS)数据

ACCLIP_Aerosol_AircraftInSitu_WB57_Data 简介 ACCLIP_Aerosol_AircraftInSitu_WB57_Data 是亚洲夏季季风化学与气候影响项目&#xff08;ACCLIP&#xff09;期间收集的原地气溶胶数据。本数据集收录了来自下一代激光质谱仪&#xff08;PALMS-NG&#xff09;、单颗粒烟尘光度…

一文读懂Partisia Blockchain,被严重低估的隐私区块链生态

在今年 3 月&#xff0c;隐私公链 Partisia Blockchain 迎来了重要的进展&#xff0c;该生态通证 $MPC 上线了交易所&#xff0c;目前 $MPC 通证可以在 Kucoin、Gate、BitMart、Bitfinex、Bitture 等平台交易&#xff0c;并将在不久后上线 MEXC 平台。 ​ 在上个月上线市场至今…

AIGC时代 可演进的私有云将蔚然成风

随着AIGC&#xff08;人工智能、大数据、云计算、物联网等技术的融合应用&#xff09;时代的来临&#xff0c;企业面临着前所未有的机遇与挑战。在这一时代背景下&#xff0c;IT基础设施如何平衡新旧资源、如何拥抱新技术应用&#xff0c;成为了企业信息化建设的核心议题。而私…

vim快捷指令

Vim是一款强大的文本编辑器&#xff0c;它提供了许多快捷指令来提高编辑效率。以下是一些常用的Vim快捷指令&#xff1a; 移动光标&#xff1a; h 向左移动一个字符j 向下移动一行k 向上移动一行l 向右移动一个字符w 跳到下一个单词的开头b 跳到前一个单词的开头e 跳到当前单词…

SpringBoot项目快速打印controller类的URL

创建一个配置类&#xff0c;实现WebMvcConfigurer接口&#xff0c;并重写addInterceptors方法来注册一个自定义的RequestMappingHandlerMapping。 import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configurati…

华为OD-C卷-小明找位置[100分]

题目描述 小朋友出操,按学号从小到大排成一列; 小明来迟了,请你给小明出个主意,让他尽快找到他应该排的位置。 算法复杂度:不高于 nlog(n); 学号为整数类型,队列规模 ≤ 10000; 输入描述 第一行:输入已排成队列的小朋友的学号(正整数),以空格隔开;例如: 93 9…

springboot项目关闭swagger防止漏洞扫描

为了应对安全扫描&#xff0c;再生产环境下关闭swagger ui 1、项目中关闭swagger 在这里用的是config配置文件的方式关闭的 Configuration EnableSwagger2 public class SwaggerConfig implements WebMvcConfigurer {Value("${swagger.enable}")private Boolean e…

【项目实战】记录一次PG数据库迁移至GaussDB测试(上)

目录 一、说明 1.1、参考文档 1.2、注意事项 1.3、环境基本情况 二、GaussDB新环境安装 2.1 配置操作环境变量 2.1.1 关闭防火墙 步骤1 执行以下命令&#xff0c;检查防火墙是否关闭。 步骤2 执行以下命令&#xff0c;关闭防火墙并禁止开机启动。 步骤3 修改/etc/sel…

Django序列化常用字段与参数

Django序列化常用字段与参数 目录 Django序列化常用字段与参数序列化常见字段序列化常见参数 序列化常见字段 字段含义字段构造方式BooleanField布尔值判断(True/False)BooleanField()NullBooleanField布尔值判断(可以为Null)NullBooleanField()CharField文本字符串CharField(…

MySQL 中datatime 与 timestamp区别

在 MySQL 中&#xff0c;DATETIME 和 TIMESTAMP 是两种用于存储日期和时间的数据类型&#xff0c;它们有以下区别&#xff1a; 存储范围&#xff1a; DATETIME&#xff1a;存储的日期和时间范围从 ‘1000-01-01 00:00:00’ 到 ‘9999-12-31 23:59:59’。TIMESTAMP&#xff1a;存…

单细胞RNA测序(scRNA-seq)Cellranger流程入门和数据质控

单细胞RNA测序(scRNA-seq)Cellranger流程入门和数据质控 单细胞RNA测序(scRNA-seq)基础知识可查看以下文章: 单细胞RNA测序(scRNA-seq)工作流程入门 单细胞RNA测序(scRNA-seq)细胞分离与扩增 1. 单细胞RNA-seq样本数据说明 样本数据来源文章:Acquired cancer re…