殷书数据结构5.8——堆
最小堆实现: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.堆是一个完全二叉树. 2.堆的每一个节点的值都大于等于(或小于等于)其子节点的值. 大于等于子节点的值我们叫它:大顶堆 小于等于子节点的值 ...
- 0x17.基础数据结构 - 二叉堆
目录 一.二叉堆 二.例题 0.AcWing 145. 超市 AcWing 146. 序列(POJ 2442) 三.HuffmanHuffmanHuffman树 1.AcWing 148. 合并果子 ...
- 【数据结构】【堆】堆的建立、插入和删除
目录 一.堆的介绍 1. 用数组表示堆,如何区分父节点和子节点? 2. 堆的种类? 二.堆的插入.删除操作 1. 几个基本操作 2. 堆的插入 3. 堆的删除 三.堆的建立 1. 建堆的原理 2. 代 ...
- 数据结构与算法 | 堆
二叉树的顺序结构 堆的概念及结构 堆的实现 二叉树的顺序结构 普通的二叉树是不适合用数组来存储的,因为可能会存在大量的空间浪费.而完全二叉树更适合使用顺序结构存储.现实中我们通常把堆(一种二叉树)使用 ...
- 数据结构 3优先队列(堆)
堆(Heaps) 我们想要这样一种数据结构,他可以进行插入和删除,但删除的话,规定每次删除的都是所有元素中最小的那一个元素.这可以利用数组和链表实现,但最好的是利用二叉树实现.如果用二叉搜索树的话删除 ...
- 【数据结构】 实现 堆 结构 ---超细致解析
目录 二叉树的性质: 二叉树的存储结构: 顺序存储: 链式存储: 堆的概念和性质: 堆的实现: 堆的初始化: 堆的插入: 向上调整函数: 堆的删除: 向下调整函数: 向上建堆: 向下建堆: TopK问 ...
- 数据结构与算法——堆的原理和实现
目录 一.堆的原理 二.堆的实现 1.堆的定义 2.堆的初始化 3.向上调整算法 4.向上调整算法代码实现 5.堆的插入 6.向下调整算法 6.堆的删除 7.堆的大小 8.判断堆是否为空 总结 一.堆 ...
- [ 数据结构-C实现 ] 堆、堆排序的分析及实现
目录 1.堆的概念结构及分类 1.2堆的分类 1.2.1 大堆 1.2.2 小堆 2. 堆的主要接口 3.堆的实现 3.1 堆的初始化 HeapInit 3.2 堆的销毁 HeapDestory ...
- 数据结构-二叉树和堆的实现
二叉树 树的概念和结构 概念 结构 树的其他概念名词 树的孩子兄弟表示法 树的实际应用 二叉树的概念和结构 概念 特殊的二叉树 二叉树的性质 二叉树的存储结构 二叉树的顺序结构-堆 堆的实现 堆的向下 ...
- 【数据结构入门】堆(Heap)
文章目录 一.堆的结构及实现(重要) 1.1 二叉树的顺序结构 1.2 堆的概念及结构 1.3 堆的实现 1.3.1 堆的向下调整算法 1.3.2 向下调整算法的时间复杂度 1.3.3 堆的创建(向下 ...
最新文章
- 今日头条在消息服务平台和容灾体系建设方面的实践与思考
- 如何在 ASP.Net Core 中实现 健康检查
- 在laravel5.8中集成swoole组件----初步测试
- 软件开发中Alpha、Beta、RC、GA版本的含义
- 阿里腾讯决战ToB“操作系统”
- 星低级格式化工具_Elixir 数据库查询工具 Ecto 讲解
- Hadoop笔记整理(二):HDFS
- iOS开发之跳转指定的tabbar控制器(二级页面跳转到指定的tabbar页面)
- 6425C-Lab8 使用组策略管理安全性(2)
- net configuration assistant 没反应_@尾款人:错过这条推送,7000多块就没了……
- 单片机毕业设计 超声波雷达可视化系统
- python模拟登陆steam
- mysql-跨库联合查询
- GPU版TensorFlow设置CPU运行的办法
- 谷歌浏览器任务栏图标变白色解决方法(亲测有效!)
- ubuntu 14.04 E450c 连不上网问题
- 华为hcia-datacom 学习日记
- ffmpeg播放器声音效果1-淡入淡出
- 飞利浦dicom_如何在飞利浦色相系统中添加第三方智能灯泡
- GBK和UTF8之间的转换 C语言