堆排序

来源:互联网 发布:linux python27 pyqt5 编辑:程序博客网 时间:2024/05/20 05:54
堆又叫二叉堆,是一种常用的数据结构。在实现中,有最大堆和最小堆两种。最小堆常常用于优先队列,堆也可以用于排序。
以最小堆为例:
最小堆中,一个结点的值不大于它的孩子。
       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)的最后一个位置,堆得大小相应的减一。

[cpp] view plain copy
  1. #include<iostream>  
  2. #include<vector>  
  3. using namespace std;  
  4. class Heap{  
  5. public:  
  6.     Heap():_size(0){}  
  7.     void insert(int n);//插入   
  8.     int delMin();//删除最小结点   
  9.     vector<int> v;  
  10. private:  
  11.     unsigned int left(int i){return 2*i+1;}//找到左孩子   
  12.     unsigned int right(int i){return 2*i+2;}//找到右孩子  
  13.     unsigned int parent(int i){return (i-1)/2;}//找到父节点   
  14.     void up(int i);//向上为维护堆   
  15.     void down(int i);  
  16.       
  17.     unsigned int _size;  
  18. };  
  19. void Heap::up(int i)  
  20. {  
  21.     if(i==0)  
  22.         return ;  
  23.     unsigned int p=parent(i);//找到父节点   
  24.     if(right(p)<v.size()) //p有有孩子  
  25.     {   
  26.          if(v[left(p)]>v[right(p)])//右孩子小于左孩子  
  27.             {  
  28.                 //交换这两个结点   
  29.                 int tmp=v[right(p)];  
  30.                 v[right(p)]=v[p]    ;  
  31.                 v[p]=tmp;  
  32.             }  
  33.           else{  
  34.             int tmp=v[left(p)];  
  35.             v[left(p)]=v[p];  
  36.             v[p]=tmp;  
  37.         }  
  38.     }  
  39.     else  
  40.     {  
  41.         int tmp=v[left(p)];  
  42.         v[left(p)]=v[p];  
  43.         v[p]=tmp;  
  44.     }  
  45.       
  46.     if(v[p]<v[parent(p)])  
  47.         up(p);  
  48. }   
  49. void Heap::down(int i)  
  50. {  
  51.     //向下维护堆  
  52.     unsigned int l=left(i);  
  53.     unsigned int r=right(i);  
  54.     unsigned int minNode; //数值最小的结点   
  55.     if(l>=v.size())//左孩子超出范围   
  56.         return ;  
  57.      if(r>=v.size()) //右孩子超出范围,只有左孩子   
  58.      {   
  59.         if(v[l]<v[i])//左孩子子小于父结点  
  60.           minNode=l;   
  61.         else return;  
  62.      }  
  63.      else//既有左孩子又有右孩子  
  64.      {  
  65.         if(v[l]<v[r])//左孩子更小   
  66.             minNode=l;  
  67.         else minNode=r;  
  68.      }  
  69.      if(v[i]<v[minNode])// 不用再向下维护堆   
  70.         return ;  
  71.      int tmp=v[minNode];  
  72.      v[minNode]=v[i];  
  73.      v[i]=tmp;  
  74.      down(minNode);  
  75.           
  76. }  
  77. void Heap::insert(int n)//插入一个元素到末尾   
  78. {  
  79.     v.push_back(n);//最后一个位置插入  
  80.     unsigned int position=v.size()-1;//插入的这个数的位置  
  81.     if(v[position]<v[parent(position)]) //改变了堆得性质,要维护  
  82.         up(position);  
  83. }  
  84. int Heap::delMin()  
  85. {  
  86.     if(v.empty())//空的   
  87.         //异常  
  88.         return 0;  
  89.      int tmp=v[0];   
  90.      v[0]=v[v.size()-1];  
  91.      v.pop_back();  
  92.      down(0);  
  93.      return tmp;  
  94. }   
  95.   
  96. int main()  
  97. {  
  98.     Heap H;  
  99.     for(int i=0;i<10;i++)  
  100.     {  
  101.         int k=rand()%100;  
  102.         H.insert(k);  
  103.         cout<<k<<" ";  
  104.     }  
  105.     cout<<endl;  
  106.     while(!H.v.empty())//无存储排序元素,直接输出   
  107.     cout<<H.delMin()<<" ";  
  108.     return 0;  
  109. }  
原创粉丝点击