堆排序
来源:互联网 发布:死去元知万事空的意思 编辑:程序博客网 时间:2024/05/18 05:49
堆又叫二叉堆,是一种常用的数据结构。在实现中,有最大堆和最小堆两种。最小堆常常用于优先队列,堆也可以用于排序。
以最小堆为例:
最小堆中,一个结点的值不大于它的孩子。
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
可以用数组实现堆得结构
图中位置为:0 1 2 3 4 5 6 7 8 9
可以看出父结点、左孩子、右孩子关系如下:
leftchild(i)=2*i+1
rightchild(i)=2*i+2
parent(i)=(i-1)/2;
向堆中添加一个元素时,添加到末尾;这时候可能破坏了堆得性质,因此要维护堆。添加在末尾,只要向上维护即可。
判断添加后是否满足堆的性质,不满足则维护这个结点。判断其父结点和父结点的左右两个孩子结点,最小的作为父结点。
之后再判断父结点是否满足堆得性质,不满足再向上维护。
从堆中删除结点时,要从堆顶删除。因为这个值是最值(最小堆的话就是最小值),之后把这个末尾结点放到堆顶。这样就破坏了堆
以最小堆为例:
最小堆中,一个结点的值不大于它的孩子。
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ /
8 9 10
可以用数组实现堆得结构
图中位置为:0 1 2 3 4 5 6 7 8 9
可以看出父结点、左孩子、右孩子关系如下:
leftchild(i)=2*i+1
rightchild(i)=2*i+2
parent(i)=(i-1)/2;
向堆中添加一个元素时,添加到末尾;这时候可能破坏了堆得性质,因此要维护堆。添加在末尾,只要向上维护即可。
判断添加后是否满足堆的性质,不满足则维护这个结点。判断其父结点和父结点的左右两个孩子结点,最小的作为父结点。
之后再判断父结点是否满足堆得性质,不满足再向上维护。
从堆中删除结点时,要从堆顶删除。因为这个值是最值(最小堆的话就是最小值),之后把这个末尾结点放到堆顶。这样就破坏了堆
的性质,向下维护堆,直到叶子结点。
堆排序时,以升序为例,可以用最小堆,每次取出堆顶元素(最小值),放到另外一个地方存储,这对内存要求为O(2N)。
也可以用最大堆,把堆顶元素(最大值)依次放到存储堆得(数组或vector)的最后一个位置,堆得大小相应的减一。
#include<iostream>#include<vector>using namespace std;class Heap{public:Heap():_size(0){}void insert(int n);//插入 int delMin();//删除最小结点 vector<int> v;private:unsigned int left(int i){return 2*i+1;}//找到左孩子 unsigned int right(int i){return 2*i+2;}//找到右孩子unsigned int parent(int i){return (i-1)/2;}//找到父节点 void up(int i);//向上为维护堆 void down(int i);unsigned int _size;};void Heap::up(int i){if(i==0)return ;unsigned int p=parent(i);//找到父节点 if(right(p)<v.size()) //p有有孩子{ if(v[left(p)]>v[right(p)])//右孩子小于左孩子 { //交换这两个结点 int tmp=v[right(p)]; v[right(p)]=v[p]; v[p]=tmp; } else{ int tmp=v[left(p)]; v[left(p)]=v[p]; v[p]=tmp; }}else{int tmp=v[left(p)];v[left(p)]=v[p];v[p]=tmp;}if(v[p]<v[parent(p)])up(p);} void Heap::down(int i){//向下维护堆unsigned int l=left(i);unsigned int r=right(i);unsigned int minNode; //数值最小的结点 if(l>=v.size())//左孩子超出范围 return ; if(r>=v.size()) //右孩子超出范围,只有左孩子 { if(v[l]<v[i])//左孩子子小于父结点 minNode=l; else return; } else//既有左孩子又有右孩子 { if(v[l]<v[r])//左孩子更小 minNode=l;else minNode=r; } if(v[i]<v[minNode])// 不用再向下维护堆 return ; int tmp=v[minNode]; v[minNode]=v[i]; v[i]=tmp; down(minNode); }void Heap::insert(int n)//插入一个元素到末尾 {v.push_back(n);//最后一个位置插入unsigned int position=v.size()-1;//插入的这个数的位置if(v[position]<v[parent(position)]) //改变了堆得性质,要维护up(position);}int Heap::delMin(){if(v.empty())//空的 //异常return 0; int tmp=v[0]; v[0]=v[v.size()-1]; v.pop_back(); down(0); return tmp;} int main(){Heap H;for(int i=0;i<10;i++){int k=rand()%100;H.insert(k);cout<<k<<" ";}cout<<endl;while(!H.v.empty())//无存储排序元素,直接输出 cout<<H.delMin()<<" ";return 0;}
0 0
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- exec与sp_executesql
- Android (Eclispe)代码自动提示功能
- 每天学JAVA——String 类
- makefile里PHONY的相关介绍
- TNS-12520 TNS:listener could not find available handler for requested type of server
- 堆排序
- Mysql数据库备份和还原常用的命令
- loadrunner 根据图片url下载图片并重命名。
- 题目1522:包含min函数的栈
- hdu 1540 线段树区间合并
- 数字图像噪声的分类
- cocos2dx 实现图片椭圆旋转选择物品界面
- 线程间的通信
- 小白学习KM算法详细总结--附上模板题hdu2255