【Data Structure】堆与优先队列
来源:互联网 发布:国外免费wifi软件 编辑:程序博客网 时间:2024/05/29 17:26
本文介绍一下重要的数据结构:堆,并以C++实现了整数最小堆。
堆是一种完全二叉树,特点是其根大于/小于其儿子,并且这个特性是递归定义的。这样的数据结构用于实现logN复杂度下进行一次最值得查询。
上图显示了一个最小堆。由于堆是完全二叉树,所以底层的数据结构用数组就可以了(当然C++里用vector更好)。那么,我们应该使堆具有哪些操作呢?首先我们应该可以实现对元素的插入。假设我们已经有一个堆,如何插入一个元素且保持对的性质呢?
首先我们写一个Heap类,底层用一个vector保存数据,把data[0]设为哨兵,这样有利于下标的操作。加入的时候,先把数据扔到数组尾部,然后再逐步往上(沿着父节点)直到调整到合适的位置。
上图实现了14的插入,具体代码如下:
void push(int temp) { data.push_back(temp); int cur=data.size()-1; while(cur!=1) { int father=cur/2; if(data[cur]<data[father]) { int t=data[cur]; data[cur]=data[father]; data[father]=t; } cur=father; } }下面我们考虑如何删除并输出最小值。显而易见,最小值就是data[1]。此时,我们把最尾部的数甩到根上,再逐步往下移动到合适位置。
由上图,我们此时应该对31进行percolate down,具体实现(包括pop)如下:
void pop() { cout<<data[1]<<endl; data[1]=data[data.size()-1]; data.pop_back(); percolateDown(1); } void percolateDown(int hole) { int child; int tmp=data[hole]; for(;hole*2<data.size();hole=child)//中间判断是不是叶子,最后更新hole(当然也可以写在循环中) { child=hole*2;//left child if(child!=data.size()-1&&data[child+1]<data[child])//if there is a right child and less then the left one child++; if(data[child]<tmp)//less than child,then swap data[hole]=data[child]; else break; } data[hole]=tmp;//补上hole,此时hole显然已经变了 }
最后,我们还要想办法实现把乱序数组初始化为堆。其实我们只要对数组的前一半用percolate down就好了。
另外,优先队列其实就是堆的一种外包装,pop操作弹出的事最值,这是利用堆来实现的,下面是heap类的完整代码(省去了析构函数),实际上就可以当做优先队列来用了。
class Heap{private: vector<int> data;public: Heap(){data.push_back(-1);} Heap(const vector<int>& item) { data.push_back(-1); for(int i=0;i<item.size();i++) data.push_back(item[i]); } void push(int temp) { data.push_back(temp); int cur=data.size()-1; while(cur!=1) { int father=cur/2; if(data[cur]<data[father]) { int t=data[cur]; data[cur]=data[father]; data[father]=t; } cur=father; } } void pop() { cout<<data[1]<<endl; data[1]=data[data.size()-1]; data.pop_back(); percolateDown(1); } void percolateDown(int hole) { int child; int tmp=data[hole]; for(;hole*2<data.size();hole=child)//中间判断是不是叶子,最后更新hole(当然也可以写在循环中) { child=hole*2;//left child if(child!=data.size()-1&&data[child+1]<data[child])//if there is a right child and less then the left one child++; if(data[child]<tmp)//less than child,then swap data[hole]=data[child]; else break; } data[hole]=tmp;//补上hole,此时hole显然已经变了 } bool empty() { return !(data.size()-1); } void print() { for(int i=1;i<data.size();i++) cout<<data[i]<<' '; cout<<endl; } void build_heap() { for(int i=(data.size()-1)/2;i>=1;i--) { percolateDown(i); } }};
0 0
- 【Data Structure】堆与优先队列
- 优先队列与堆
- 优先队列与堆
- 堆与优先队列
- 优先队列 与 堆
- 堆与优先队列
- 【data structure】之栈与队列
- 最大堆与优先队列
- 堆与优先队列详解
- 堆排序与优先队列
- 优先队列与堆排序
- c++ 堆与优先队列
- 二叉堆与优先队列
- 优先队列与堆排序
- 堆与堆排序—优先队列
- [data structure] heap 堆
- UVA - 11995 - I Can Guess the Data Structure!(栈、队列、优先队列)
- UVA 11995 I Can Guess the Data Structure!【栈+队列+优先队列基本用法】
- double的精确度
- Python字符编码详解
- Android数据存储访问——文件存储
- 从内存管理、内存泄漏、内存回收探讨C++内存管理
- VS2013编译Qt5.3.2的静态库
- 【Data Structure】堆与优先队列
- HDU_ACM-2051 十进制转为二进制数
- HDU_ACM-2052 Picture
- zigBee协议栈的NV操作
- C++ Primer 学习笔记 整形
- Android开发笔记之文件访问(二)
- 求int 的最大值
- Codeforces 4C-Registration system(map)
- delcookie