建立堆,堆排序的詳細實現過程,C++完整程式碼
堆的基本概念不在此介紹,各位看官自行百度。由於堆的特性導致堆可以用陣列進行模擬,所以堆排序其實是在陣列(即堆)上進行排序的過程,在所有堆的操作中,都離不開一個操作:調整堆,該過程使堆保持堆的性質(大堆或小堆的性質)。在介紹堆排序之前必要要介紹如何建立堆,由於堆是使用陣列儲存的,所有我的理解是,建堆的過程就是堆化陣列,即使給定的陣列具有堆的性質。堆化的過程其實就是調整堆的過程,我們把調整堆的過程定義成一個單獨的函式void AdjustHeap(int heap[], int root_index, int heap_length),引數分別是代表堆的陣列,要調整的堆的根節點在陣列中的下標,注意是下標,建議讀者自己畫個圖模擬調整堆的過程。第三個引數是堆的長度,在這裡就讓他等於陣列的長度,其實可以不相等。
調整堆的過程如下:
1.根據根節點下標,確定左右子節點的下標。
2.找出根節點和左右子節點中最小值的下標,注意該過程要判斷邊界,即左右子節點的下標是否超出堆的長度。
3.如果最小值的下標等於根節點的下標,函式返回。
4.否則,交換把根節點與最小值交換,由於交換可能破壞了最小值所在子樹的對性質,所以遞迴呼叫AdjustHeap函式。
那麼現在還有一個問題,就是堆化的時候,從哪個節點開始調整堆呢?這個也是建堆的關鍵,我們可以這樣想,子節點已經是堆了,無需在調整了,所以我們沒必要從最後一個節點開始調整,一般是從(heap_length/2)開始調節,一直到下標1為止(堆的下標一般從1開始,0位置不用),從(heap_length/2)開始調節的原因是完全二叉樹的性質決定的。這樣遍歷一遍,對每個節點呼叫堆調整函式就完成建堆了。
堆排序的思想比較簡單,取出堆的第一個元素,調整堆,迴圈下去,知道取完為止。實現的過程就是先把堆頂元素和堆的最後一個元素互換,堆長度減1,再調整堆,知道堆的長度為1。這樣就使堆排序的空間複雜度為O(1)了,注意的是大頂堆排完序之後陣列中元素的順序是從小到大,小頂堆是從大到小。
完整程式碼如下:
#include <iostream> #define Max 11 int heap[Max]; void AdjustHeap(int heap[], int root_index, int heap_length) //調整堆,這裡是最小堆 { int left_child_index = root_index * 2; int right_child_index = left_child_index + 1; int min_index = root_index; if (left_child_index < heap_length && right_child_index < heap_length) { if (heap[left_child_index] < heap[root_index]) { if (heap[left_child_index] < heap[right_child_index]) min_index = left_child_index; else min_index = right_child_index; } else { if (heap[right_child_index] < heap[root_index]) min_index = right_child_index; else min_index = root_index; } } if (left_child_index < heap_length && right_child_index >= heap_length) //這種情況是左子節點是最後一個元素的情況 { if (heap[left_child_index] < heap[root_index]) min_index = left_child_index; else min_index = root_index; } if (min_index != root_index) { int t = heap[root_index]; heap[root_index] = heap[min_index]; heap[min_index] = t; AdjustHeap(heap,min_index,heap_length); } return; } void CreateHeap(int heap[], int heap_length) //建堆 { for (int i = (heap_length / 2); i >= 1; --i) AdjustHeap(heap, i, heap_length); } int main() { heap[0] = -1; for (int i = 1; i != Max; ++i)//輸入陣列 std::cin >> heap[i]; CreateHeap(heap, Max); //建堆,即堆化 for (int i = 0; i != Max; ++i) std::cout << heap[i] << " "; std::cout << std::endl; //堆建好的堆進行排序 int t = Max; while (t != 1) { int tmp = heap[t - 1]; heap[t - 1] = heap[1]; heap[1] = tmp; AdjustHeap(heap, 1, t-1); --t; } for (int i = Max - 1; i != 0; --i) std::cout << heap[i] << " "; std::cout << std::endl; }