----------------

该篇文章经提醒有一些错误,暂时没有时间修改,请勿参考。

该篇文章经提醒有一些错误,暂时没有时间修改,请勿参考。

----------------

堆是特殊的队列,从堆中取元素是按照元素的优先级大小,而不是元素进入队列的先后顺序。因此,堆也通常被称为“优先队列”。

堆的最常用结构是用二叉树表示,不特指的话,他是一棵完全二叉树。因此通常不必用指针,而是用数组来实现堆的存储。我们

知道,完全二叉树用数组来表示,就相当于把全完二叉树的层序遍历依次存入数组中,知道最后一个节点。

需要注意的是,所用的数组的起点为1,而不是0。这样的目的是很容易能够从父节点(i)找到子节点[ 2i ] [ 2i+1 ],反过来也很容易从子节点(j)找到父节点[ j/2 ]。

堆的特性:

用数组来表示完全二叉树是堆的第一特性:堆的结构特性

任一节点的值与其子节点的值是相关的:部分有序性

相关性的不同决定了两种不同的基本堆:最大堆(MaxHeap)(任一节点大于等于其子节点)和最小堆(MinHeap)(任一节点小于等于其子节点)。注意,兄弟节点之间没有约束关系。

当我们需要小键值优先时,使用最小堆;需要大键值优先时,使用最大堆。

首先来看一下堆的一般结构体实现:

typedef struct HNode * heap;//结构体指针
struct HNode{ElementType *Data;//表示堆的数组 大小要在用户输入的元素个数上+1int Size;//数组里已有的元素(不包含a[0]) int Capacity; //数组的数量上限
};
typedef heap MaxHeap; //定义一个最大堆
typedef heap MinHeap; //定义一个最小堆

创建:

//mheap表示maxHeap或者minHeap
mHeap creatMHeap(int size){mHeap heap = (mHeap)malloc(sizeof(struct Hnode));heap->data = (int*)malloc(sizeof(int)*(size+1));//从a[1]开始保存数 所以数组数量要+1heap->Size = 0;heap->Capacity=size;heap->data[0] = MAXData OR MINDATA;//岗哨 稍后会提到return heap;
}

接下来用代码来表示最大堆和最小堆的相关操作:

最大堆(MaxHeap):

插入:

从新增的最后一个节点的父节点开始,用要插入的元素向下过滤上层节点(比该元素小的下移)。

bool insertToHeap(maxHeap heap, int x){//查看是否已经满了if (heap->Size == heap->Capacity) {return false;}int i = ++heap->Size;//新增的节点位置for (; heap->data[i/2]<x; i/=2) {
//此处的判断 如果向上到了a[1]还没停止的话 需要让其就停在a[1]处 所以要在a[0]的位置放置一个"岗哨"
//这个岗哨对于最大堆来说要放入一个 比数组中所有数都大的数 这样在比较a[0]和x时 a[0]>x 循环就会停下来heap->data[i] = heap->data[i/2];}heap->data[i] = x;return true;
}

删除:

从根节点开始,用最大堆中的最后一个元素向上过滤下层节点(比该元素大的上移)。

int deleteHeap(maxHeap heap){//判断是否空if (heap->Size==0) {return false;}int top = heap->data[1];//堆顶元素(最大)int last = heap->Size--;//取出数组最后一个元素int parent = 1;int child;for (; parent*2<=heap->Size; parent=child) {child = 2*parent;//左子节点//查找是否有右子节点 并且 右子节点的元素大于左子节点if (child!=heap->Size && heap->data[child]<heap->data[child+1]) {child++;//右子节点if (last<heap->data[child]) {heap->data[parent] = heap->data[child];}else{//找到了位置break;}}}heap->data[parent] = last;return top;
}

构造:

虽说构造一个最大堆时只要把一个个元素按照插入方法插入到数组中即可完成。但是其时间复杂度是(O(N log N))。我们有一种更简单的方式,使得时间复杂度下降到O(N)。

1.将输入的元素按顺序放入完全二叉树(数组)中。

2.调整各个节点的位置,满足最大堆的有序性。

调整的过程就是从最后一个父节点开始倒序到根节点,逐一向下进行过滤操作(同删除的向下过滤一样,不过过滤元素就是父节点本身的元素)。

void percDown(maxHeap heap, int n){int top,parent,child;top = heap->data[n];//取出父节点元素//向下过滤for (parent = n; parent*2<heap->Size; parent=child) {child = 2*parent;if (child!=heap->Size && heap->data[child]<heap->data[child+1]) {child++;if (heap->data[child]<=n) {break;}elseheap->data[child] = heap->data[parent];}}heap->data[parent] = top;
}void buildMaxHeap(maxHeap heap){for (int i=heap->Size/2; i>0; i--) {//从最后一个父节点开始percDown(heap, i);}
}

最小堆(MaxHeap):

由于最大堆和最小堆只是元素的顺序位置不同,具体的操作只是细节判断的修改,就只提下插入和删除操作把:

插入:


bool insertMinHeap(minHeap heap, int x){//判断是否满了if (heap->Size == heap->Capacity){return false;}int p = ++heap->Size;for (; heap->data[p/2]<x; p/=2) {
//这里是最小堆  所以在a[0]位置的岗哨保存了比数组中所有元素都小的元素heap->data[p] = heap->data[p/2];}heap->data[p] = x;return true;
}

删除:

int deleteFromMinHeap(minHeap heap){int top = heap->data[1];int last = heap->data[heap->Size--];int parent,child;for (parent = 1; parent*2<heap->Size; parent=child) {child = parent*2;//注意这里是存在右子节点 并且 右子节点比左子节点小    if (child!=heap->Size && heap->data[child] > heap->data[child+1]) {child++;//如果比右子节点还小if (heap->data[child]>last) {break;}else{//下滤heap->data[parent] = heap->data[child];}}}heap->data[parent] = last;return top;
}

最大堆最小堆的实现(C语言)相关推荐

  1. C++实现最大堆最小堆

    目录 堆和栈的区别 最大堆与最小堆 最大堆的操作 最大堆的插入操作 最大堆的弹出操作 最大堆的C++代码实现 最小堆概念 最小堆的插入操作 最小堆的弹出操作 最小堆的C++代码实现 最大堆最小堆的应用 ...

  2. Golang实现最大堆/最小堆

    Golang实现最大堆/最小堆 参考: https://yangjiahao106.github.io/2019/01/15/golang-%E6%9C%80%E5%A4%A7%E5%A0%86%E5 ...

  3. java 最小堆_堆排序 最大堆 最小堆 Java 实现

    堆 一点疑惑,堆排序是就地排序,所以空间复杂度是 O(1).但是,比如我有一个数组,建立一个最小堆,然后每次取出最小堆的顶点.建立最小堆需要额外空间? 不深究了,归并排序需要额外空间. 堆是完全二叉树 ...

  4. C++STL中的最大堆,最小堆

    堆,优先队列,头文件和队列是同一个#include<queue> #include<iostream> #include<queue> using namespac ...

  5. C++ 最大堆最小堆与push_heap pop_heap

    make_heap:根据不同参数生成大顶堆或者小顶堆,默认大顶堆. make_heap(_RAIter,_RAIter) 默认生成大顶堆 make_heap(_RAIter,_RAIter,_Comp ...

  6. python 中的最大堆和最小堆(heapq库)

    目录 首先来看一下什么是最大堆和最小堆? python heapq库中的一些常用方法 小试牛刀 首先来看一下什么是最大堆和最小堆? 最大堆:一种经过排序的完全二叉树,其中任意非终端节点数值均不小于其左 ...

  7. WebServer代码解读(3)【最小堆定时器与队列】

    文章目录 1 - 处理事件 1-1 接收新连接 1-2 最小堆定时器 1-4 将request加入线程池 1-5 处理request 1 - 处理事件 因为epoll_wait函数已经返回了需要处理的 ...

  8. 数据结构——最大堆和最小堆(C语言)

    定义: 最大堆和最小堆都是一棵完全二叉树. 最大堆:是指根节点的关键字值是堆中的最大关键字值,且每个节点若有儿子节点,其关键字值都不小于其儿子节点的关键字值. 最小堆:是指根节点的关键字值是堆中的最小 ...

  9. 使用最大堆和最小堆实现中位数的查找

    参考链接:双堆维护数组中位数 用堆维护中位数的意思是说,设计两个堆,第一个堆(大顶堆)存放小于中位数的元素,第二个堆(小顶堆)存放大于中位数的元素. 下面是双堆维护中位数的语言描述: 1.初始化的时候 ...

最新文章

  1. Kubernetes 架构(下)【转】
  2. 现实世界的 Windows Azure:HRG将应用程序扩展到移动设备,削减80 %的启动成本
  3. 留念,第一次在C中调用lua成功!
  4. linux kill信号列表
  5. 获取项目版本号与设置引导页的判断条件
  6. 函数实现不放在头文件的原因,及何时可以放头文件的情况【转】
  7. BitTorrent协议规范(BitTorrent Protocol Specification)系列之元信息文件结构(Metainfo File Structure)-第二部分...
  8. Linux crontab
  9. Pycharm虚拟环境的使用
  10. 生成订单30分钟未支付,则自动取消,该怎么实现?原来大公司的最有解是这样的!...
  11. python2.7 matplotlib_Python 2.7中的Numpy、SciPy、MatPlotLib安装与配置
  12. 登陆界面万能密码绕过
  13. 计算机应用基础网课试题及答案2020,2019-2020年度公共课计算机应用基础考试试题附答案(5页)-原创力文档...
  14. Ajax学习日志(五)—— 如何传递json格式请求参数
  15. 游戏服务端(MMORPG)的基础算法一、AOI
  16. PHP全栈学习笔记7
  17. MacbookPro下载word文件显示dms怎么办
  18. python实践输出星星_打印星星 - Python
  19. 《两种文化》——读书报告
  20. XmlReader简介

热门文章

  1. 等量点电荷matlab,点电荷电场的MATLAB作图.pdf
  2. Flutter的Text控件显示纯英文时高度和汉字不一致的问题
  3. phpmyadmin通过日志写shell
  4. 11.①事件冒泡:取消冒泡event.cancelBubble=true或.sopImmediatePropagation()②事件绑定addEventListener(参数1,参2,参3)③事件传播
  5. C++:实现量化capfloor edcoupon设置利率上下限优惠券测试实例
  6. PS抠图方法、技巧大集合
  7. assasin谈设计模式
  8. 《钢之炼金术士》启示录
  9. 【Audio】查看手机的声卡信息
  10. 好用的蓝牙耳机有哪些推荐?2022蓝牙耳机性价比之王