堆排序

来源:互联网 发布:死去元知万事空的意思 编辑:程序博客网 时间: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; 
 向堆中添加一个元素时,添加到末尾;这时候可能破坏了堆得性质,因此要维护堆。添加在末尾,只要向上维护即可。
 判断添加后是否满足堆的性质,不满足则维护这个结点。判断其父结点和父结点的左右两个孩子结点,最小的作为父结点。
 之后再判断父结点是否满足堆得性质,不满足再向上维护。
 
 从堆中删除结点时,要从堆顶删除。因为这个值是最值(最小堆的话就是最小值),之后把这个末尾结点放到堆顶。这样就破坏了堆

 的性质,向下维护堆,直到叶子结点。

堆排序时,以升序为例,可以用最小堆,每次取出堆顶元素(最小值),放到另外一个地方存储,这对内存要求为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
原创粉丝点击