文章目录

    • 使用说明
  • 1.插入式建堆
  • 2.直接在数组基础上调整排序建堆

使用说明

本文的堆以小根堆为例,给出模板
使用时将ElementType 修改为对应的数据类型就好

1.插入式建堆

建一个空堆,将元素一个一个插入,调整

#include <cstdio>
#include <cstdlib>using namespace std;typedef struct HeapStruct {ElementType *Element;int Size;int MaxSize;
} Heap, *MinHeap;// 方法一: 创建一个大小为 MaxSize 的堆
MinHeap Create_Heap(int MaxSize) {MinHeap heap = (MinHeap *) malloc (sizeof(Heap)); //  申请一个堆 heap->Element = (ElementType *) malloc (MaxSize+1)*sizeof(ElementType); // 为堆申请存储元素的空间大小,即堆的能够存储的结点数 heap->Size = 0; // 堆的当前元素数 heap->MaxSize = MaxSize; // 堆的最大存储空间 heap->Element[0] = INT_MIN; // 将指针数组的 0 号位置置为无穷小,堆顶从 1 号开始
}// 使用后释放堆申请的空间
void Destroy(MinHeap heap) {free(heap->Element); // 先释放堆结点的数组空间 free(heap);  // 再释放堆结点的空间
} // 判断堆是否为空
bool IsEmpty(MinHeap heap) {return (heap->Size == 0);
}// 判断堆是否满了
bool IsFull(MinHeap heap, ElementType Size) {return (heap->Size == heap->MaxSize);
} // 向堆中插入元素
void Insert(MinHeap heap, ElementType item) {int i = 0;// 检查是否有空间可以插入元素if(IsFull(heap)) {printf("Heap is full!\n");return ;} /*将item加入为堆的一个叶子结点,然后向上调整至合适的位置插入,到堆顶结束*/heap->Size ++; // 堆中的元素数量增加1for(i = heap->Size; heap->Element[i / 2] > item; i = i / 2) { // 向上与父节点做比较 heap->Element[i] = heap->Element[i / 2]; // 父节点下移 } heap->Element[i] = item;
}// pop并返回堆顶
ElementType Pop(MinHeap heap) { ElementType item, temp; // 取出堆顶int parent = 0, child = 0;if(IsEmpty(heap)) {printf("Heap is Empty!\n");return heap->Element[0]; // 相当于一种安全保护 }/*如果堆不空,则将堆顶取出作为返回值,将最后一个结点也就是二叉堆的一个叶子结点放在堆顶。将堆顶向下调整至合适位置后停止 */ item = heap->Element[1];temp = heap->Element[heap->Size];heap->Size --; // 堆中元素减少一个for(int parent = 1; parent * 2 <= heao->Size; parent = child) {child = parent * 2;// 找出左右子节点中较小的那个if(child != heap->Size && (heap->Element[child] > heap->Element[child + 1])) {child++;} // 比较父节点与子节点的大小,如果父节点大就,则二者互换位置继续寻找合适的插入位置,否则?if(temp > heap->Element[child]) {heap->Element[parent] = heap->Element[child];}else break;}heap->Element[child] = temp;return item;
} int main() {int x, n;scanf("%d", &n);MinHeap H = Create(n);for(int i = 1; i <= n; i++) {scanf("%d", &x);Insert(H, x);}return 0;
}

2.直接在数组基础上调整排序建堆

直接将存数据的数组建堆,从每颗小的子树开始调整,

// 方法二: 已知一个数组,创建一个由数组组成的最小堆
MinHeap BuildMinHeap(ElementType *Element, int Size, int MaxSize) {MinHeap H = Create(MaxSize); // 创建一个空的ElementType temp;int parent = 0, child = 0;// 判断存储空间够不够用if (Size > H->MaxSize) {printf("最小堆的存储空间不够用\n");return NULL; } // 将数组中的元素先全部复制到堆里for(int i = 0; i < Size; i++) {H->Element[i+1] = Element[i];} H->Size = Size;// 给最小堆元素排序/*从最后一个节点的父节点开始,自右向左,自下向上将每个父节点与其两个子节点做比较后上调直到堆顶与其左右子节点做比较 ,然后将堆顶下沉该建堆方法比一个一个插入更优,因为不需要将叶子结点从堆顶移动到叶子位置(当然最坏情况是一样的) */for(parent = H->Size / 2; parent >= 1; parent--) {temp = H->Element[parent];for(; parent * 2 <= H->Size; parent = child) {child = parent * 2;// 如果左右子树都存在,将父节点与其中较小的比较后选择是否下沉if(child != H->Size && (H->Element[child] > H->Element[child + 1])) {child ++;}// 选择父节点是否下沉if(temp > H->Element[child]) {H->Element[parent] = H->Element[child];} else break;}H->Element[parent] = temp;}return H;
}

完整代码

#include <cstdio>
#include <cstdlib>using namespace std;typedef struct HeapStruct {ElementType *Element;int Size;int MaxSize;
} Heap, *MinHeap;// 方法一: 创建一个大小为 MaxSize 的堆
MinHeap Create_Heap(int MaxSize) {MinHeap heap = (MinHeap *) malloc (sizeof(Heap)); //  申请一个堆 heap->Element = (ElementType *) malloc (MaxSize+1)*sizeof(ElementType); // 为堆申请存储元素的空间大小,即堆的能够存储的结点数 heap->Size = 0; // 堆的当前元素数 heap->MaxSize = MaxSize; // 堆的最大存储空间 heap->Element[0] = INT_MIN; // 将指针数组的 0 号位置置为无穷小,堆顶从 1 号开始
}// 方法二: 已知一个数组,创建一个由数组组成的最小堆
MinHeap BuildMinHeap(ElementType *Element, int Size, int MaxSize) {MinHeap H = Create(MaxSize); // 创建一个空的ElementType temp;int parent = 0, child = 0;// 判断存储空间够不够用if (Size > H->MaxSize) {printf("最小堆的存储空间不够用\n");return NULL; } // 将数组中的元素先全部复制到堆里for(int i = 0; i < Size; i++) {H->Element[i+1] = Element[i];} H->Size = Size;// 给最小堆元素排序/*从最后一个节点的父节点开始,自右向左,自下向上将每个父节点与其两个子节点做比较后上调直到堆顶与其左右子节点做比较 ,然后将堆顶下沉该建堆方法比一个一个插入更优,因为不需要将叶子结点从堆顶移动到叶子位置(当然最坏情况是一样的) */for(parent = H->Size / 2; parent >= 1; parent--) {temp = H->Element[parent];for(; parent * 2 <= H->Size; parent = child) {child = parent * 2;// 如果左右子树都存在,将父节点与其中较小的比较后选择是否下沉if(child != H->Size && (H->Element[child] > H->Element[child + 1])) {child ++;}// 选择父节点是否下沉if(temp > H->Element[child]) {H->Element[parent] = H->Element[child];} else break;}H->Element[parent] = temp;}return H;
} // 使用后释放堆申请的空间
void Destroy(MinHeap heap) {free(heap->Element); // 先释放堆结点的数组空间 free(heap);  // 再释放堆结点的空间
} // 判断堆是否为空
bool IsEmpty(MinHeap heap) {return (heap->Size == 0);
}// 判断堆是否满了
bool IsFull(MinHeap heap, ElementType Size) {return (heap->Size == heap->MaxSize);
} // 向堆中插入元素
void Insert(MinHeap heap, ElementType item) {int i = 0;// 检查是否有空间可以插入元素if(IsFull(heap)) {printf("Heap is full!\n");return ;} /*将item加入为堆的一个叶子结点,然后向上调整至合适的位置插入,到堆顶结束*/heap->Size ++; // 堆中的元素数量增加1for(i = heap->Size; heap->Element[i / 2] > item; i = i / 2) { // 向上与父节点做比较 heap->Element[i] = heap->Element[i / 2]; // 父节点下移 } heap->Element[i] = item;
}// pop并返回堆顶
ElementType Pop(MinHeap heap) { ElementType item, temp; // 取出堆顶int parent = 0, child = 0;if(IsEmpty(heap)) {printf("Heap is Empty!\n");return heap->Element[0]; // 相当于一种安全保护 }/*如果堆不空,则将堆顶取出作为返回值,将最后一个结点也就是二叉堆的一个叶子结点放在堆顶。将堆顶向下调整至合适位置后停止 */ item = heap->Element[1];temp = heap->Element[heap->Size];heap->Size --; // 堆中元素减少一个for(int parent = 1; parent * 2 <= heao->Size; parent = child) {child = parent * 2;// 找出左右子节点中较小的那个if(child != heap->Size && (heap->Element[child] > heap->Element[child + 1])) {child++;} // 比较父节点与子节点的大小,如果父节点大就,则二者互换位置继续寻找合适的插入位置,否则?if(temp > heap->Element[child]) {heap->Element[parent] = heap->Element[child];}else break;}heap->Element[child] = temp;return item;
} 

手写堆模板(指针数组)相关推荐

  1. Duan2baka的手写堆模板!

    随手翻到了去年写的手写堆- -手写堆真是太蠢了 Lheap:小根堆 Rheap:大根堆 #include<algorithm> #include<cstring> #inclu ...

  2. 恶补C++:重载手写堆结构体lower_bound()vector构造、析构函数setmappairstack

    部分目录 运算符重载 C++ 函数调用运算符 () 重载 我的经历 关于this 关于友元 附:重载函数 C++补充 优先队列 手写堆 手写堆的存储 手写堆的两个基本操作 插入节点的原理 求当前堆的最 ...

  3. 堆(手写堆包含STL)

     文章目录 前言 一.堆的定义 二.堆的分类及性质(STL的用法) 1.堆的分类 2.STL的用法 3.堆的性质 三.手写堆(重点) 1.手写堆的思想 2.函数模块 3.操作模块 四.完整代码 + 注 ...

  4. 【CCCC】L2-012 关于堆的判断 (25分),,手写堆,二叉树编号,向上调整

    problem L2-012 关于堆的判断 (25分) 将一系列给定数字顺序插入一个初始为空的小顶堆H[].随后判断一系列相关命题是否为真.命题分下列几种: x is the root:x是根结点: ...

  5. 堆排序(如何手写堆)

    文章目录 1.一道算法题(堆排序模板题) 2.数组模拟小根堆的原理 3.浙大PAT算法题:堆排序还是插入排序 1.一道算法题(堆排序模板题) acwing838. 堆排序 838. 堆排序 分析: 这 ...

  6. hihoCoder 第136周 优化延迟(二分答案+手写堆)

    题目1 : 优化延迟 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho编写了一个处理数据包的程序.程序的输入是一个包含N个数据包的序列.每个数据包根据其重要程度不同 ...

  7. [转载] 管Q某犇借的手写堆

    跟gxy大神还有yzh大神学了学手写的堆,应该比stl的优先队列快很多.  其实就是维护了一个二叉堆,写进结构体里,就没啥了...  据说达哥去年NOIP靠这个暴力多骗了分 合并果子... 1 tem ...

  8. Djkastra堆(手写堆)优化版

    直接上代码 代码中的注释掉的部分为C++优先队列实现 #include<cstdio> #include<cstdlib> #include<iostream> # ...

  9. C++手写堆的实现(LuoguP3378模板)

    关于堆 二叉堆有两种形式,分别为大根堆和小根堆. 大根堆有两个性质: 1.根节点点权为所有节点点权中的最大值; 2.任意节点的点权都大于它的子节点. 同样地,小根堆也具有两个性质,并且与大根堆相反: ...

最新文章

  1. pybind opencv mat
  2. mysql取出数据外键_mysql数据表有外键,应注意的几点(目前学习所获得的经验)...
  3. SAP IDES、DEV、QAS、PRD都是什么含义
  4. TNS-12545: Connect failed because target host or object does not exist
  5. boost::log::sinks::text_ipc_message_queue_backend用法的测试程序
  6. CF--思维练习--CodeForces - 221C-H - Little Elephant and Problem (思维)
  7. MySql数据同步FEDERATED引擎
  8. vue 不识别svg_vue配置svg 图标显示不出来
  9. 小程序抽象组件使用示例
  10. JS实现自动轮播图效果(自适应屏幕宽度+手机触屏滑动)
  11. Http 请求处理流程[转]
  12. MM模块采购收货的错误解决方案(2)
  13. 内网安全-隧道穿透漫游
  14. 数字图像处理复习记录(二)邻接、连通和形态学处理
  15. python 网络调试助手
  16. python打印输出如下图形_python题目要求:输出如下图片中的图形
  17. 第十四周项目一 平衡二叉树
  18. 计算机音乐数字乐谱青芒,弱水三千(戏腔付)
  19. Facebook更名Meta,扎克伯格押注元宇宙
  20. Avfoundation 相机指定裁剪区域

热门文章

  1. DeepLabv3:语义图像分割
  2. 想学图像分割,强烈建议从这5篇图像分割算法综述
  3. 如何用OpenCV制作一个低成本的立体相机
  4. python06-集合和序列
  5. 你应该知道的高性能无锁队列Disruptor
  6. 开启Mac充电提示音
  7. 分层PHP性能分析工具--xhprof
  8. matlab7.1(ERROR STARTING DESKTOP)解决
  9. BuildSql增加了【生成数据库文档】的功能了
  10. 查看oracle已经锁定的表,Oracle中查询被锁定的表