最小堆

来源:互联网 发布:淘宝最火的女装店铺 编辑:程序博客网 时间:2024/05/13 08:29

最大堆和最小堆是二叉堆的两种形式。

  1. 最大堆:根结点的键值是所有堆结点键值中最大者的堆。
  2. 最小堆:根结点的键值是所有堆结点键值中最小者的堆。

不失一般性,只讨论根结点为最小层的情况。

插入[编辑]

只需要将节点插在二叉树的最后一个叶子结点位置,然后比较它对它父亲节点的大小,如果大则停止;如果小则交换位置,然后对父亲节点递归该过程直至根节点。复杂度为O(log(n))。

一般来说,插入的位置可以不是最后一个叶子节点,可以作为任意中间节点的孩子节点插入,将这个叶子节点变为中间节点后,按上文所说的方法调整节点顺序以保证维持堆特性不变。

删除[编辑]

要从堆中删除一个节点,用最后一个节点替换掉根节点,然后调整节点顺序以维持堆特性。

堆定义文件:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #ifndef MINHEAP_H  
  2. #define MINHEAP_H  
  3. #include <iostream>  
  4. using std::cin;    
  5. using std::cout;    
  6. using std::endl;     
  7. using std::ostream;   
  8.   
  9.   
  10. template <typename T>  
  11. class MinHeap  
  12. {  
  13.   
  14.     friend ostream& operator << (ostream& os,const MinHeap<T> &heap)  
  15.     {  
  16.         for(int i = 0; i < heap.currentSize; i++)  
  17.         {  
  18.             os << heap.heapArray[i] << "\t";  
  19.         }  
  20.         return os;  
  21.     }  
  22.   
  23. private:  
  24.     T *heapArray;//存放堆数据的数组  
  25.     int maxSize;//堆所能容纳的最大元素数目  
  26.     int currentSize;//当前堆中元素数目  
  27.   
  28.     void swap(int posx,int posy)//辅助函数,交换位置x和y的元素  
  29.     {  
  30.         T temp = heapArray[posx];  
  31.         heapArray[posx] = heapArray[posy];  
  32.         heapArray[posy] = temp;  
  33.     }  
  34.   
  35.     void siftDown(int left)  //向下筛  
  36.     {  
  37.         int currentPos = left;                  // 标识父结点  
  38.         int childPos = leftChild (currentPos);  // 标识关键值较小的子结点  
  39.         while (childPos < currentSize)   
  40.         {                       // 过筛  
  41.             if ((childPos < currentSize-1) && (heapArray[childPos] > heapArray[childPos + 1]))  
  42.             {  
  43.                 childPos++;                     // j指向右子结点,也就是元素最小的子节点  
  44.             }  
  45.   
  46.             if (heapArray[currentPos] > heapArray[childPos])   
  47.             {  
  48.                 swap(currentPos,childPos);  
  49.                 currentPos = childPos;  
  50.                 childPos = leftChild(childPos);                     // 向下继续调整  
  51.             }  
  52.             else   
  53.             {  
  54.                 break// 调整到位  
  55.             }  
  56.         }  
  57.     }  
  58.   
  59.     void siftUp(int currentPos) //向上调整  
  60.     {  
  61.   
  62.         int parentPos = parent(currentPos);//父节点位置  
  63.         while(currentPos > 0)//调整到0号位置则应停止  
  64.         {  
  65.             if(heapArray[currentPos] < heapArray[parentPos])//向上调整  
  66.             {  
  67.                 swap(currentPos,parentPos);  
  68.                 currentPos = parentPos;  
  69.                 parentPos = parent(currentPos);  
  70.             }  
  71.             else  
  72.             {  
  73.                 break;//已经到位  
  74.             }  
  75.         }  
  76.     }  
  77.   
  78.     void buildHeap()  
  79.     {  
  80.         for(int i = currentSize/2 - 1; i >= 0; i--)  
  81.         {  
  82.             siftDown(i);//反复调用筛选函数  
  83.         }  
  84.     }  
  85.   
  86. public:  
  87.     MinHeap(const int size) : maxSize(size)  
  88.     {  
  89.         if(size <= 0)  
  90.         {  
  91.             return;  
  92.         }  
  93.         heapArray = new T[maxSize];  
  94.         currentSize = 0;  
  95. /* 
  96.  
  97.         //此处进行堆元素的赋值工作 
  98.         heapArray[0] = 19;                 //亦可以用插入的办法构造 
  99.         heapArray[1] = 8; 
  100.         heapArray[2] = 35; 
  101.         heapArray[3] = 65; 
  102.         heapArray[4] = 40; 
  103.         heapArray[5] = 3; 
  104.         heapArray[6] = 7; 
  105.         heapArray[7] = 45; 
  106.         currentSize = 8; 
  107.  
  108.         buildHeap();*/  
  109.           
  110.     }  
  111.   
  112.     ~MinHeap()  
  113.     {  
  114.         delete []heapArray;  
  115.     }  
  116.     bool isEmpty() const// 如果堆空,则返回真  
  117.     {  
  118.         return currentSize == 0;  
  119.     }  
  120.   
  121.     bool isLeaf(int pos) const//是否叶子节点  
  122.     {  
  123.         return (pos >= currentSize/2) && (pos <= currentSize-1);  
  124.     }  
  125.   
  126.     int leftChild(int pos) const//返回左孩子位置  
  127.     {  
  128.         return 2 * pos + 1;  
  129.     }  
  130.   
  131.     int rightChild(int pos) const//返回右孩子位置  
  132.     {  
  133.         return 2 * pos + 2;  
  134.     }  
  135.   
  136.     int parent(int pos) const//返回父节点位置  
  137.     {  
  138.         return (pos-1)/2;  
  139.     }  
  140.   
  141.     bool insert(T &newNode)//向堆中插入新元素newNode  
  142.     {  
  143.         if(currentSize == maxSize)//堆空间已经满  
  144.         {  
  145.             return false;  
  146.         }  
  147.         else  
  148.         {  
  149.             heapArray[currentSize] = newNode;  
  150.             siftUp(currentSize);//向上调整  
  151.             currentSize++;  
  152.             return true;  
  153.         }  
  154.     }  
  155.   
  156.     bool remove(int pos, T& node)       // 删除给定下标的元素  
  157.     {  
  158.         if(pos < 0 || pos > currentSize - 1)  
  159.         {  
  160.             return false;  
  161.         }  
  162.   
  163.         node = heapArray[pos];  
  164.         heapArray[pos] = heapArray[--currentSize];// 用最后的元素值替代删除位置的元素  
  165.   
  166.         if(heapArray[pos] < heapArray[parent(pos)])// 当前元素小于父结点,需要上升调整  
  167.         {  
  168.             siftUp(pos);  
  169.         }  
  170.         else  
  171.         {  
  172.             siftDown(pos);//向下筛  
  173.         }  
  174.   
  175.         return true;  
  176.     }  
  177.   
  178.     bool removeMin(T& node)     // 删除堆顶的元素  
  179.     {  
  180.         /*if(currentSize == 0) 
  181.         { 
  182.             cout << "堆为空,无法移除!" << endl; 
  183.             return false; 
  184.         } 
  185.         else 
  186.         { 
  187.             node = heapArray[0]; 
  188.             swap(0,--currentSize);//交换堆顶和最后一个元素 
  189.             if(currentSize > 1) 
  190.             { 
  191.                 siftDown(0); 
  192.             }            
  193.             return true; 
  194.         }*/  
  195.         return remove(0,node);  
  196.     }  
  197. };  
  198. #endif  

测试代码:

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include "MinHeap.h"  
  2.   
  3.   
  4. int main()  
  5. {  
  6.     MinHeap<int> minheap(8);  
  7.     cout << "初始化堆:" << minheap << endl;  
  8.   
  9.     int Key[] = {19,8,35,65,40,3,7,45} ;    
  10.   
  11.     cout << "建堆前:" << endl;     
  12.     for(int i = 0;i < 8; i++)    
  13.     {            
  14.         minheap.insert(Key[i]);  
  15.         cout<< Key[i] << "\t";  
  16.     }  
  17.     cout << endl;  
  18.   
  19.     cout << "建堆后:" << endl;  
  20.     cout << minheap << endl;  
  21.   
  22.     int elem;  
  23.     cout<< "删除给定下标(3)的元素:" << endl;  
  24.     minheap.remove(3,elem);  
  25.     cout<<  elem << " deleted." << endl;  
  26.     cout << "现在堆: " << endl;  
  27.     cout <<  minheap << endl;  
  28.   
  29.     //插入45  
  30.     cout<< "插入45:" << endl;  
  31.     minheap.insert(elem);  
  32.     cout << "现在堆: " << endl;  
  33.     cout <<  minheap << endl;  
  34.   
  35.     cout << "从堆顶删除最小值:" ;  
  36.     minheap.removeMin(elem);  
  37.     cout << elem << endl;  
  38.     cout << "现在堆: " << endl;  
  39.     cout <<  minheap << endl;  
  40.   
  41.     system("pause");  
  42.     return 0;  
  43. }  

0 0