堆排序演算法解析

2021-08-07 03:51:04 字數 2395 閱讀 4388

堆排序是利用堆的性質進行的一種選擇排序。下面先討論一下堆。

11.堆堆實際上是一棵完全二叉樹,其任何一非葉節點滿足性質:

key[i]<=key[2i+1]&&key[i]<=key[2i+2]或者key[i]>=key[2i+1]&&key>=key[2i+2]

即任何一非葉節點的關鍵字不大於或者不小於其左右孩子節點的關鍵字。

堆分為大頂堆和小頂堆,滿足key[i]>=key[2i+1]&&key>=key[2i+2]稱為大頂堆,滿足 key[i]<=key[2i+1]&&key[i]<=key[2i+2]稱為小頂堆。由上述性質可知大頂堆的堆頂的關鍵字肯定是所有關鍵字中最大的,小頂堆的堆頂的關鍵字是所有關鍵字中最小的。 2

2.堆排序的思想

利用大頂堆(小頂堆)堆頂記錄的是最大關鍵字(最小關鍵字)這一特性,使得每次從無序中選擇最大記錄(最小記錄)變得簡單。

其基本思想為(大頂堆):

1)將初始待排序關鍵字序列(r1,r2....rn)構建成大頂堆,此堆為初始的無序區;

2)將堆頂元素r[1]與最後乙個元素r[n]交換,此時得到新的無序區(r1,r2,......rn-1)和新的有序區(rn),且滿足r[1,2...n-1]<=r[n]; 

3)由於交換後新的堆頂r[1]可能違反堆的性質,因此需要對當前無序區(r1,r2,......rn-1)調整為新堆,然後再次將r[1]與無序區最後乙個元素交換,得到新的無序區(r1,r2....rn-2)和新的有序區(rn-1,rn)。不斷重複此過程直到有序區的元素個數為n-1,則整個排序過程完成。

操作過程如下:

1)初始化堆:將r[1..n]構造為堆;

2)將當前無序區的堆頂元素r[1]同該區間的最後乙個記錄交換,然後將新的無序區調整為新的堆。

因此對於堆排序,最重要的兩個操作就是構造初始堆和調整堆,其實構造初始堆事實上也是調整堆的過程,只不過構造初始堆是對所有的非葉節點都進行調整。

下面舉例說明:

給定乙個整形陣列a=,對其進行堆排序。

首先根據該陣列元素構建乙個完全二叉樹,得到

3然後需要構造初始堆,則從最後乙個非葉節點開始調整,調整過程如下:

420和16交換後導致16不滿足堆的性質,因此需重新調整

5這樣就得到了初始堆。

即每次調整都是從父節點、左孩子節點、右孩子節點三者中選擇最大者跟父節點進行交換(交換之後可能造成被交換的孩子節點不滿足堆的性質,因此每次交換之後要重新對被交換的孩子節點進行調整)。有了初始堆之後就可以進行排序了。

6此時3位於堆頂不滿堆的性質,則需調整繼續調整

7這樣整個區間便已經有序了。

從上述過程可知,堆排序其實也是一種選擇排序,是一種樹形選擇排序。只不過直接選擇排序中,為了從r[1...n]中選擇最大記錄,需比較n-1次,然後從r[1...n-2]中選擇最大記錄需比較n-2次。事實上這n-2次比較中有很多已經在前面的n-1次比較中已經做過,而樹形選擇排序恰好利用樹形的特點儲存了部分前面的比較結果,因此可以減少比較次數。對於n個關鍵字序列,最壞情況下每個節點需比較log2(n)次,因此其最壞情況下時間複雜度為nlogn。堆排序為不穩定排序,不適合記錄較少的排序。

測試程式 8

#include

#include

using namespace std;

void heapadjust(int *a,int i,int size)  //調整堆 

if(rchild<=size&&a[rchild]>a[max])

if(max!=i)

}        

}void buildheap(int *a,int size)    //建立堆 

} void heapsort(int *a,int size)    //堆排序 

} int main(int argc, char *argv)

;int a[100];

int size;

while(scanf("%d",&size)==1&&size>0)

return 0;}

堆排序演算法解析

首先來引入乙個例子 如何使用選擇排序?肯定是每一次遍歷然後把大的放到最後面。當然,前面也可以 我感覺堆排序其實和選擇差不多。堆排序也是每次取出最大值,然後把最大值放後面 但是想學會堆排序,首先要知道什麼是堆 堆的定義 邏輯上 乙個完全二叉樹 物理上 借助向量實現 為什麼能用乙個向量來間接的弄乙個完全...

堆排序解析

首先要了解堆的性質,我這裡簡答總結一下 這裡說的是小堆 1 堆是一棵完全二叉樹 2 對於大堆中的任何乙個非葉子節點,節點的值必須小於左右孩子節點值。由此可知,對於小堆而言,根節點就是最小值了,那麼我們每次拿走根節點,拿走的順序就是遞增序列的。排序的元素在陣列中,而堆也是一棵完全二叉樹,所以直接用陣列...

深度解析堆排序

堆排序,其實就是用陣列儲存,利用完全二叉樹的性質,對其進行二叉樹的操作,通過構建大頂堆 小頂堆 找到最大值 最小值 與最後乙個節點交換,然後總個數減一,然後重複此操作,最後得到有序序列。如果不理解大頂堆與小頂堆的話,建議先看看 基本思路是 構建出始堆 將堆頂元素與最後乙個節點交換 遞迴此操作。感覺思...