演算法 排序演算法的介紹與總結(三)

2021-07-01 21:34:12 字數 3934 閱讀 1961

1、什麼是堆

堆是一種樹結構,更準確的說是完全二叉樹。並且每個非葉節點的資料大於或等於(小於或等於)其左、右子結點的資料,這樣堆結構的根結點為最大值(最小值),堆稱為最大堆(最小堆)。所以可以歸納為:堆是乙個完全二叉樹,非葉結點與左右子結點的資料有一定的大小關係。

2、什麼是堆排序

完整的堆排序需要經過反覆的兩個步驟:構造堆結構和堆排序輸出。

用通俗的話來說就是:

(1)將一組資料放到乙個完全二叉樹中去,再通過資料交換,使完全二叉樹變成堆。

(2)根據堆的定義我們知道,堆的根結點是最大值(最小值),這樣我們將跟結點的值輸出,就得到了這一組資料的最大值(最小值)。

(3)使剩餘的資料再次構成乙個堆,然後輸出跟結點。

(4)不斷重複上述步驟就可以實現原資料按順序輸出。

那現在的問題就是如何構造堆以及如何堆排序輸出。

3、如何構造堆構造堆結構就是把原始的無序資料按照前面堆結構的定義進行調整。

(1)將原始的無序資料放到乙個完全二叉樹的各個結點中去。

(2)然後由完全二叉樹的最下層的非葉結點開始逐層向上進行調整(因為葉結點沒有左右子樹,所以一定是符合條件的),直到所有結點(在調整過程中某些非葉結點可能需要經過多次調整)最後都滿足堆結構的條件為止。整個過程其實就是將最大值(最小值)不斷向上移動,直到移到跟結點為止。

(3)在調整過程中,假設父結點與左結點的大小關係不合規則,需要進行值得交換。交換之後父結點與左右結點的大小關係符合要求了,但是此時如果左結點是乙個非葉結點(也有子結點),那麼左結點與該左結點的子結點之間就有可能不符合規則,即還需要對子結點進行調整,直到葉結點

下面給出乙個實際的例子來分析構造堆的過程。

(1)將原始資料構成乙個完全二叉樹。

(2)最後乙個非葉結點為結點4,從該結點進行堆化操作。該結點只有左子樹且49>38。按照最大堆的定義,是使4和8這兩個結點互換位置

(3)上述完全二叉樹中倒數第2個非葉結點是結點3,顯然結點3及其子結點已經構成堆結構,無需對該結點進行堆化操作。

(4)上述完全二叉樹中倒數第3個非葉結點是結點2,對該結點進行堆化操作。由於結點2的兩個子結點中結點5的值較大,因此使結點2與結點5進行比較。因為65<97,此時需要將結點2與結點5互換資料。這樣結點2及其子及結點構成堆

(5)上述二叉樹中倒數第4個非葉結點是結點1,對該結點進行堆化操作,由於結點1的兩個子節點中結點2的值較大。所以使結點1與結點2進行比較。67小於97,因此將結點1與結點2互換資料。這時結點2的值已經改變,需要重新對結點2及其子結點進行堆化操作,因為結點1與結點2互換資料可能破壞了結點2和其子結點構成的堆。這樣結點1及其子結點構成堆結構。

4、堆排序輸出

(1)根據堆結構的特點,堆結構的根結點也就是最大值。這裡按照從小到大排序,因此將其放到陣列的最後,將結點8與結點1互換。

(2)結點8的值38換到跟結點之後,對除最後乙個結點外的其他結點結點重新執行前面介紹的構造堆的過程,重新得到堆。

(3)重複上述過程,取此時堆結構的根結點(最大值)進行互換,放在陣列的後面。此時結點1與結點7互換。

(4)然後重複將剩餘的資料構造堆結構,取根結點與最後乙個結點交換。結果如下圖。

(5)再進一步執行堆排序輸出,結點1與結點3互換,結果如下圖

(6)堆最後的兩個資料進行處理,得到最終的結果

5、具體的**實現具體**在這就不解釋了,**中的注釋寫的非常詳細。

/**

*@author mr0

* */

public

class

p4_6_select_heapsort

}

/***@param a

* 將乙個完全二叉樹堆化(最大堆)

* 核心思想:找到二叉樹中最後乙個葉節點的父節點(第乙個非葉節點),比較父節點與左右節點(左右節點至少存在乙個)的值,

* 這時會出現兩種情況:1、左右節點的某乙個值比父節點大,此時將較大的值與父節點互換,記錄下進行了互換操作的左右節點的id,

* 再呼叫heapify對以左(右)節點為跟節點的子二叉樹進行堆化 2、左右節點都比父節點小,此時父節點與子節點之間沒有值得交換

* 不需要對以左(右)節點為父節點的子二叉樹進行堆化,迴圈到下乙個非葉節點。再迴圈1、2的判斷過程

* 最終就完成了完全二叉樹的堆化。

*/public

static

void

buildheap(int a)

}/**

*@param a

*@param id

*@param max

* 將以id為下標的節點所對應的子樹堆化

*/public

static

void

heapify(int a,int id,int max)else

if(righta[largest])

if(largest != id)

system.out.print("largest="+largest+" ");

system.out.print("i="+id);

system.out.println("");

heapify(a,largest,max); //對交換值後的子節點進行堆化操作。}}

/***@param a

*@param b

*@param c

* 交換a陣列中bc下標元素的值。

*/public

static

void

swap(int a,int b,int c)

public

static

void

main(string args);

system.out.println("排序前陣列順序為:");

for(int i=0;i" ");

}system.out.println("");

heapsort(array);

system.out.println("");

system.out.println("排序後的陣列順序為:");

for(int i=0;i" ");}}

}

排序演算法的比較與總結

歸併 穩定,o nlogn 遞迴實現 大類排序方法 時間複雜度 空間複雜度 穩定性實現方法 備註交換法 冒泡法最差 平均都是o n 2 最好是o n 1穩定 n較小時較好 交換法雞尾酒冒泡法 最差 平均都是o n 2 最好是o n 1穩定 n較小時較好 交換法快速排序 平均o nlogn 最壞是o ...

排序演算法 8 對比與總結

排序演算法 時間複雜度 空間複雜度 排序方式 穩定性平均情況 最好情況 最壞情況 氣泡排序 o n n o n o n n o 1 內排序穩定 簡單選擇排序 o n n o n n o n n o 1 內排序不穩定 直接插入排序 o n n o n o n n o 1 內排序穩定 希爾排序 o n ...

排序演算法介紹

排序也稱排序演算法 sort algorithm 排序是將一組資料,依指定的順序進行排列的過程。1 內部排序 指將需要處理的所有資料都載入到內部儲存器 記憶體 中進行排序。2 外部排序法 資料量過大,無法全部載入到記憶體中,需要借助外部儲存 檔案等 進行排序。1 穩定 如果 a 原本在 b 前面,而...