自己实现的堆结构

来源:互联网 发布:linux 常用命令 top 编辑:程序博客网 时间:2024/05/07 03:57

       之前写过一个堆及其算法的博客(参考:堆及其算法),但是STL源码考虑的问题很多,所以没有突出堆的核心内容。在此用C++实现了堆。

#include <iostream>using namespace std;template <class T>class heap{private:int m_capacity;                  //堆的最大容量int m_n;       //第一个空元素的标号T*m_px;   //维护堆的数据   void swap(const int i, const int j){T t=m_px[i];m_px[i]=m_px[j];m_px[j]=t;}void shiftUp(int i);               //!!!这两个内部(私有)函数才是关键!!!
void shiftDown(int i);public:heap(int size):m_capacity(size){m_n=0;m_px=new T[size];}~heap(){delete[] m_px;}int size(){return m_n;}void insert(T a);T popMax();void makeHeap(T a[],int len);//void sort();};template <class T>void heap<T>::shiftUp(int i){int t;while (i>0){t=(i-1)/2;if (m_px[i]>m_px[t]){swap(i,t);i=t;}else break;}}template <class T>void heap<T>::shiftDown(int i){T temp=m_px[i];int j=2*i+1;while(j<m_n){if(j+1<m_n)                  //存在右子结点if(m_px[j]<m_px[j+1])    //且右子结点大j++;if (temp>=m_px[j]) break;else{m_px[i]=m_px[j];i=j;j=2*i+1;}}m_px[i]=temp;}template <class T>void heap<T>::insert(T a){m_px[m_n++]=a;shiftUp(m_n-1);}template<class T>void heap<T>::makeHeap(T a[],int len){if (len>m_capacity){cout << "The array is too long!!";return;}for (int i=0;i<len;i++){insert(a[i]);}}template <class T>T heap<T>::popMax(){T t=m_px[0];m_px[0]=m_px[--m_n];shiftDown(0);return t;}/*template <class T>void heap<T>::sort(){int i=m_n-1;while(m_n>0){swap(0,--m_n);shiftDown(0);}while(i>0){cout<<m_px[i--]<<endl;}}*/int main(){int a[10]={9,8,7,6,5,4,2,3,1,0};heap<int> testheap(20);testheap.makeHeap(a,10);for (int i=0;i<10;i++){cout << testheap.popMax() << endl;}//testheap.sort();cout << "finished"<<endl;return 0;}

        其实这个结构称为优先级队列就更加合适,其中排序操作和测试的部分注释掉了。这个结构有一个缺陷,就是排序一个长度为n的数组,需要额外的n个元素空间,如果只编写一些函数来对数组进行堆操作的话,那么这个n个元素空间的开销可以节省下来。但是这些函数的编写存在一个难点,如何确定一直变化的堆大小,要以参数的形式将堆的大小传入。其实就是一个标号,这个标号确定了,堆和有(无)序区的临界点。