最小堆实现:MinHeap.h

#include <iostream>
using namespace std;
#define DefaultSize 10template<class E>
class MinHeap {public:MinHeap(int sz = DefaultSize);  //构造函数:建立空堆MinHeap(E arr[], int n);      //构造函数:通过一个数组创建堆~MinHeap() { delete[] heap; }    //析构函数bool insert(const E& x);      //将x插入到最小堆中bool removeMin(E& x);            //删除堆顶元素(min value)void HeapSort();bool isEmpty() const{return (currentSize==0) ? true : false;}          //判断堆是否是空bool isFull() const{return (currentSize==maxHeapSize) ? true : false;}           //判断堆是否已满void makeEmpty(){currentSize=0;}          //置空堆 void output(){for (int i = 0; i < currentSize; i ++) std::cout << heap[i] << ' ';   //数组元素输出}
private:E* heap;                        //存放最小堆元素的数组int currentSize;                //最小堆中当前元素的个数int maxHeapSize;               //最小堆最多存放元素个数void siftDown(int start, int m);//从start到m下滑调整为最小堆void siftUp(int start);          //从start到0上滑调整为最小堆
};//函数定义
template<class E>
MinHeap<E>::MinHeap(int sz) {//方式1建立最小堆,动态创建maxHeapSize = (DefaultSize < sz) ? sz : DefaultSize;heap = new E[maxHeapSize];if (nullptr == heap) {std::cerr << "内存分配失败" << std::endl;exit(EXIT_FAILURE);}currentSize = 0;
}template<class E>
MinHeap<E>::MinHeap(E arr[], int n) {//方式2创建最小堆,从已知数组中复制数据,然后调整为最小堆结构//函数参数:已知数组数据、数据个数maxHeapSize = (DefaultSize < n) ? n : DefaultSize;heap = new E[maxHeapSize];if (nullptr == heap) {std::cerr << "内存分配失败" << std::endl;exit(EXIT_FAILURE);}for (int i = 0; i < n; i ++) {heap[i] = arr[i];                          //数据copy}currentSize = n;//利用完全二叉树中元素的排列规律,找到最初调整位置,也就是最后的分支节点int currentPos = (currentSize - 1) / 2;           while (currentPos >= 0) {                       //自底向上逐步扩大形成堆siftDown(currentPos, currentSize - 1);     //局部调整currentPos--;                             //向前换一个分支节点}
}
template<class E>
bool MinHeap<E>::insert(const E& x) {//共有函数:将x插入到最小堆中if (isFull()) {                                   //判断堆是否已经满std::cerr << "Heap Fulled" << std::endl;return false;                               }heap[currentSize] = x;                            //将x元素插入到数组最后siftUp(currentSize);                           //堆排序,从大到小 currentSize++;                                  //对当前大小增加1return true;
}template<class E>
bool MinHeap<E>::removeMin(E& x) {//删除堆顶元素,引用返回if (0 == currentSize) {std::cout << "Heap Emptyed" << std::endl;return false;}x = heap[0];heap[0] = heap[currentSize - 1];currentSize--;siftDown(0, currentSize - 1);                 //借助函数对堆再一次调整return true;
}template<class E>
void MinHeap<E>::siftDown(int start, int m) {//私有函数:从节点start开始到m为止,自上向下比较,如果子女值小于父节点的值,//则关键码小的上浮,继续向下层比较,这样将一个集合的局部调整为最小堆int i = start;int j = 2 * i + 1;                               //通过公式2x+1求得x左子女位置E temp = heap[i];                               //temp记录原来的的数据while (j <= m) {if (j < m && heap[j] > heap[j + 1]) {j = j + 1;                              //j指向左右子女中较小的一个}if (heap[j] >= temp) {break;                                    //已经符合最小堆的结构,无需调整}else {                                     //否则调整,并更新i,j至下一层heap[i] = heap[j];                      i = j;j = 2 * i + 1;}}heap[i] = temp;                                   //完成调整后的数据交换
}template<class E>
void MinHeap<E>::siftUp(int start) {//私有函数:从节点start开始到节点0为止,自下向上比较,如果子女的值小于父节点的值//则相互交换,这样讲集合重新调整为最小堆(注意比较元素E的逻辑运算符重载)int j = start;int i = (j - 1) / 2;                                //找左子女公式的逆运算公式E temp = heap[j];while (j > 0) {if (heap[i] <= temp) {break;}else {heap[j] = heap[i];j = i;i = (j - 1) / 2;}}heap[j] = temp;
}//堆排序,从大到小
template<class E>
void MinHeap<E>::HeapSort(){int len=currentSize;for(int i=len-1;i>=0;i--){swap(heap[0],heap[i]);siftDown(0,i-1);}
}

主函数main.cpp

#include<iostream>
#include"MinHeap.h"
using namespace std; int main()
{int data[8] {0};//用数组数据建最小堆测试for (int i = 0; i < 8; i ++) {cin >> data[i];}MinHeap<int> minheap(data, 8);minheap.output();cout << endl;//向堆内插入元素测试int value{11};minheap.insert(value);minheap.output();cout << endl;//从堆内删除元素测试int delValue{ 0 };minheap.removeMin(delValue);minheap.output();cout << endl;minheap.HeapSort();minheap.output();return 0;
}

堆的应用:
1.堆排序:

借助上面写好的堆数据实现
template<class E>
void MinHeap<E>::HeapSort(){int len=currentSize;for(int i=len-1;i>=0;i--){swap(heap[0],heap[i]);siftDown(0,i-1);}
}
简单版本(堆调整、建堆、堆排序)
#include<iostream>
using namespace std;void heapify(int *arr,int i,int n){if(i>=n) return;int l=2*i+1,r=2*i+2,large=i;if(l<n&&arr[l]>arr[large]){large=l; }if(r<n&&arr[r]>arr[large]){large=r;}if(large!=i){swap(arr[i],arr[large]);heapify(arr,large,n); }
}void build_heap(int *arr,int n){for(int i=(n-2)/2;i>=0;i--){heapify(arr,i,n);}
}//堆排序,
void HeapSort(int *arr,int n){build_heap(arr,n);for(int i=n-1;i>=0;--i){swap(arr[i],arr[0]);heapify(arr,0,i-1);   }
}int main(){int n;cin>>n;int arr[n];  for (int i=0;i<n;++i) {cin >> arr[i];  }HeapSort(arr,n);for (int i = 0; i < n; ++i) {cout << arr[i]<< " "; }return 0;
}

2.堆中第k大元素(黄宇算法设计与分析习题14.2)

#include<iostream>
using namespace std;void heapify(int *arr,int i,int n){if(i>=n) return;int l=2*i+1,r=2*i+2,large=i;if(l<n&&arr[l]>arr[large]){large=l; }if(r<n&&arr[r]>arr[large]){large=r;}if(large!=i){swap(arr[i],arr[large]);heapify(arr,large,n); }
}void build_heap(int *arr,int n){for(int i=(n-2)/2;i>=0;i--){heapify(arr,i,n);}
}//堆中第k大元素
int findKthLargest(int *arr,int n,int k){build_heap(arr,n);for(int i=n-1;i>=n-k+1;--i){swap(arr[i],arr[0]);heapify(arr,0,i-1);   }return arr[0];
}int main(){int n,k;cin>>n;int arr[n];  for (int i=0;i<n;++i) {cin >> arr[i];  }cin>>k;cout<<findKthLargest(arr,n,k);return 0;
}

殷书数据结构5.8——堆相关推荐

  1. 数据结构与算法---堆的基本操作

    堆的定义 堆可以看做是一种特殊的树,堆结构满足两个条件: 1.堆是一个完全二叉树. 2.堆的每一个节点的值都大于等于(或小于等于)其子节点的值. 大于等于子节点的值我们叫它:大顶堆 小于等于子节点的值 ...

  2. 0x17.基础数据结构 - 二叉堆

    目录 一.二叉堆 二.例题 0.AcWing 145. 超市 AcWing 146. 序列(POJ 2442) 三.HuffmanHuffmanHuffman树 1.AcWing 148. 合并果子 ...

  3. 【数据结构】【堆】堆的建立、插入和删除

    目录 一.堆的介绍 1. 用数组表示堆,如何区分父节点和子节点? 2. 堆的种类? 二.堆的插入.删除操作 1. 几个基本操作 2. 堆的插入 3. 堆的删除 三.堆的建立 1. 建堆的原理 2. 代 ...

  4. 数据结构与算法 | 堆

    二叉树的顺序结构 堆的概念及结构 堆的实现 二叉树的顺序结构 普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费.而完全二叉树更适合使用顺序结构存储.现实中我们通常把堆(一种二叉树)使用 ...

  5. 数据结构 3优先队列(堆)

    堆(Heaps) 我们想要这样一种数据结构,他可以进行插入和删除,但删除的话,规定每次删除的都是所有元素中最小的那一个元素.这可以利用数组和链表实现,但最好的是利用二叉树实现.如果用二叉搜索树的话删除 ...

  6. 【数据结构】 实现 堆 结构 ---超细致解析

    目录 二叉树的性质: 二叉树的存储结构: 顺序存储: 链式存储: 堆的概念和性质: 堆的实现: 堆的初始化: 堆的插入: 向上调整函数: 堆的删除: 向下调整函数: 向上建堆: 向下建堆: TopK问 ...

  7. 数据结构与算法——堆的原理和实现

    目录 一.堆的原理 二.堆的实现 1.堆的定义 2.堆的初始化 3.向上调整算法 4.向上调整算法代码实现 5.堆的插入 6.向下调整算法 6.堆的删除 7.堆的大小 8.判断堆是否为空 总结 一.堆 ...

  8. [ 数据结构-C实现 ] 堆、堆排序的分析及实现

      目录 1.堆的概念结构及分类 1.2堆的分类 1.2.1 大堆 1.2.2 小堆 2. 堆的主要接口 3.堆的实现 3.1 堆的初始化 HeapInit 3.2 堆的销毁 HeapDestory ...

  9. 数据结构-二叉树和堆的实现

    二叉树 树的概念和结构 概念 结构 树的其他概念名词 树的孩子兄弟表示法 树的实际应用 二叉树的概念和结构 概念 特殊的二叉树 二叉树的性质 二叉树的存储结构 二叉树的顺序结构-堆 堆的实现 堆的向下 ...

  10. 【数据结构入门】堆(Heap)

    文章目录 一.堆的结构及实现(重要) 1.1 二叉树的顺序结构 1.2 堆的概念及结构 1.3 堆的实现 1.3.1 堆的向下调整算法 1.3.2 向下调整算法的时间复杂度 1.3.3 堆的创建(向下 ...

最新文章

  1. 今日头条在消息服务平台和容灾体系建设方面的实践与思考
  2. 如何在 ASP.Net Core 中实现 健康检查
  3. 在laravel5.8中集成swoole组件----初步测试
  4. 软件开发中Alpha、Beta、RC、GA版本的含义
  5. 阿里腾讯决战ToB“操作系统”
  6. 星低级格式化工具_Elixir 数据库查询工具 Ecto 讲解
  7. Hadoop笔记整理(二):HDFS
  8. iOS开发之跳转指定的tabbar控制器(二级页面跳转到指定的tabbar页面)
  9. 6425C-Lab8 使用组策略管理安全性(2)
  10. net configuration assistant 没反应_@尾款人:错过这条推送,7000多块就没了……
  11. 单片机毕业设计 超声波雷达可视化系统
  12. python模拟登陆steam
  13. mysql-跨库联合查询
  14. GPU版TensorFlow设置CPU运行的办法
  15. 谷歌浏览器任务栏图标变白色解决方法(亲测有效!)
  16. ubuntu 14.04 E450c 连不上网问题
  17. 华为hcia-datacom 学习日记
  18. ffmpeg播放器声音效果1-淡入淡出
  19. 飞利浦dicom_如何在飞利浦色相系统中添加第三方智能灯泡
  20. GBK和UTF8之间的转换 C语言

热门文章

  1. php开源 饭馆记账软件_个人记账软件 - 开源免费
  2. python将xls转换为xlsx_python – 如何将xls转换为xlsx
  3. 第9天Sqltie数据库
  4. Head First设计模式-适配器模式
  5. 概率与数理统计学习总结四---连续型随机变量及其概率密度
  6. Java后端工程师在做什么
  7. 微信企业号开发:openapi回调地址请求不通过
  8. 工作中,掌握这四个说话技巧,再也不用担心自己不会说话
  9. PAT 乙级 1072 开学寄语 (20分)
  10. 如何提升固定资产盘点效率