选择排序之——堆排序(c/c++)
堆是一類特殊的數據結構的統稱。堆在邏輯結構上可以看作為樹,但是物理結構是通過順序表來實現的。堆總是滿足下列性質:
堆中某個節點的值總是不大于或不小于其父節點的值;
堆總是一棵完全二叉樹。
將根節點最大的堆叫做最大堆或大頂堆,根節點最小的堆叫做最小堆或小頂堆。
堆是非線性數據結構,相當于一維數組,但有兩個直接后繼。
堆的定義如下:n個元素的序列{k1,k2,ki,…,kn}當且僅當滿足下關系時,稱之為堆。
(ki <= k2i,ki <= k2i+1)或者(ki >= k2i,ki >= k2i+1), (i = 1,2,3,4...n/2)
堆排序算法:按照堆的定義建成小(大)頂堆,輸出堆頂的最小(大)數,再對剩余元素重新建堆,再輸出,再建堆......
? ? (1)初始時如何建堆?(2)如何調整剩余元素使成為一個堆? ??
? ? 問題的關鍵在于調整,初始建堆也可以看做是調整所有元素成為一個堆。
堆總是一個完全二叉樹,而樹的葉子節點自身便是一個堆,不需要調整;只有有孩子的節點才會不符合堆的要求。本文堆排序算法的數組從下標1開始,假設數組有n個數,下標自1至n,則最后一個有孩子的節點的下標是n/2(向下取整)。從最后一個有孩子的節點往前進行查找,n/2-1,n/2-2,.......,1。
比如小頂堆 13 36 24 85 47 30 53 91共8個數,8/2=4,從第四個數85開始,將它自身作為根節點來調整堆,再對第三個數24開始調整堆...直到第一個數,這樣這8個數就構成了一個堆。小頂堆建好之后,第一個數便是最小的數,將它與第八個數相交換,再對前7個數調整建堆,建好之后將此時第一個數與第七個數相交換,再對前6個數建堆......
本算法通過建立小頂堆來進行排序,這樣得到的輸出序列為降序序列。
堆排序算法的時間復雜度為o(nlogn),空間復雜度為0(1)。它是一種不穩定的排序方法。
heapAdjust函數用來調整數組使成為一個堆,如下:該數列除了arr[s]外其余數均滿足堆定義,它對數列arr{s...m]進行處理,使得該數列均滿足堆定義。
void heapAdjust(int* arr, int s, int m){//數組arr[s...m]中除了arr[s]外其余元素均符合堆的定義,現調整arr[s]使得//arr[s...m]均滿足堆定義int i;int rc = arr[s];for (i = 2 * s; i <= m; i *= 2){if (i < m&&arr[i] > arr[i + 1])++i;if (rc<arr[i])break;arr[s] = arr[i];s = i;}arr[s] = rc;}完整代碼如下:
#include<iostream>#define N 20void heapSort(int* arr, int num);void heapAdjust(int* arr, int s, int m);int main(){int a[N+1] = {-0, 3, 2, 4, 6, 7, 5, 18, 9, 0, 1,16, 8, 20, 33, 28, 64, 19, 31, 30, 25 };//處理下標1到20之間的數。for (int i = 1; i <=N; i++){std::cout << a[i] << " ";}std::cout << '\n'; heapSort(a,N);for (int i = 1; i <=N; i++){std::cout << a[i] << " ";}std::cout << '\n';return 0;}void heapSort(int* arr, int num){//下面注釋的遞歸處理也是可以的,但是效率不高/*if (num == 1)return;*/int i, temp;for (i = num / 2; i > 0; i--)heapAdjust(arr, i, num);for (i = num; i>1; i--){temp = arr[i];arr[i] = arr[1];arr[1] = temp;heapAdjust(arr, 1, i-1);}/*temp = arr[1];arr[1] = arr[num];arr[num] = temp;heapSort(arr, --num);*/}void heapAdjust(int* arr, int s, int m){//數組arr[s...m]中除了arr[s]外其余元素均符合堆的定義,現調整arr[s]使得//arr[s...m]均滿足堆定義int i;int rc = arr[s];for (i = 2 * s; i <= m; i *= 2){if (i < m&&arr[i] > arr[i + 1])++i;if (rc<arr[i])break;arr[s] = arr[i];s = i;}arr[s] = rc;}?
?
?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的选择排序之——堆排序(c/c++)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 选择排序之——简单选择排序(c/c++)
- 下一篇: 归并排序之——二路归并(c/c++)