本博文內容為堆排序的實現,以及堆排序的相關筆試題,如求數組的topk元素,優先隊列實現等
1.堆排序的實現原理:堆排序是基於二叉樹實現的,主要步驟為:先建立二元堆積(堆元素從 n/2 - - 1 執行向上調整操作) (二元堆積分為小根堆與大根堆),再不斷執行以下步驟:將根項目與根底元素互換,且將未排序的堆總元素減一,並執行將根頂元素向下調整操作,直到未排序堆總元素為0具體代碼如下:
//////////////////////////////////// 實現小根堆的相關操作/////////////////////////////////bool isLess(int a, int b) { return a<b; }void exch(int &a, int &b) { int temp=a;a=b;b=temp;}//向上調整函數void shiftup(int *data, int pos){while(pos/2>=1) //pos/2>=1要注意{if(isLess(data[pos/2], data[pos])) break;exch(data[pos/2], data[pos]);pos=pos/2;}}//向下調整函數void shiftdown(int *data, int pos, int n){while(2*pos<=n){//data[0]代表數組的元素個數,2*pos<=n細節要注意int k=2*pos;if(k<n && isLess(data[k+1], data[k])) k++; //k<n要注意if(isLess(data[pos], data[k])) break;exch(data[pos], data[k]);pos=k;}}//堆排序(降序排序)void heap_sort(int *data){int i=0;for(i=data[0]/2; i>=1; i--)shiftup(data, i);int n = data[0];while(n>=1){//n>=1要注意exch(data[1], data[n]);shiftdown(data, 1, --n); //--n要注意}}
2. 優先隊列(根頂元素為最小值)的實現優先隊列的實現原理是利用了二元堆積的性質,一般至少包括2個操作:插入元素:insert(先判斷插入後元素的個數(n+1)是否超過優先隊列的最大個數,在將data[++n]=val,並將該元素進行向上調整操作)返回隊列的最小值(或最大值): extractmin(首先判斷優先隊列中是否有元素(n-1<0),再儲存優先隊列的首元素,將最後一個元素與第一個元素交換,並將元素個數減一,最後對優先隊列首元素執行向下調整操作)具體代碼:
///////////////////////////////////// 實現優先隊列的相關操作///////////////////////////////////class prior_queue{public:prior_queue(int m);//建構函式void insert(int val);//插入元素int extractmin();//取優先隊列的最小值~prior_queue();//解構函式private:int *m_data;int maxsize;int n;private:void shiftdown(int pos);//向下調整void shiftup(int pos);//向上調整void exch(int &a, int &b) { int temp=a; a=b; b=temp; }};prior_queue::prior_queue(int m){m_data = new int[m+1];maxsize=m;n=0;}prior_queue::~prior_queue(){delete[] m_data;}void prior_queue::shiftdown(int pos){while(2*pos<=n){int k=2*pos;if(k<n && m_data[k+1]<m_data[k]) k++;if(m_data[pos]<m_data[k]) break;exch(m_data[pos], m_data[k]);pos=k;}}void prior_queue::shiftup(int pos){while(pos/2>=1){if(m_data[pos/2]<m_data[pos]) break;exch(m_data[pos], m_data[pos/2]);pos=pos/2;}}void prior_queue::insert(int val){n = n+1;if(n>maxsize)return ;m_data[n]=val;shiftup(n);}int prior_queue::extractmin(){if(n-1<0)return 0;int min=m_data[1];exch(m_data[1], m_data[n--]);shiftdown(1);return min;}
3.輸出數組中的top_max_k元素(或者top_max_k)實現原理:建立一個k個元素的小根堆,來輸出數組中的最大的k和元素(或者大根堆,來輸出數組中的最小的k的元素)先對已知數組前k個元素建立一個k小根堆,再將數組的元素(下標從k+1 - - n)與小根堆根頂元素比較,大則交換,並執行向下調整操作,直至遍曆完數組中的全部元素具體代碼:
void top_max_k(int *data, int k){int i=0;for(i=k/2; i>=1; i--)shiftup(data, i);i=k+1;while(i<=data[0]){if(data[i]>data[1]){exch(data[i], data[1]);shiftdown(data, 1, k); //shitdown見堆排序中的shiftdown函數}i++;}}