在提到堆積排序前我們先講講樹的資料結構,因為在堆積排序中會使用到某一種樹。
那樹是甚麼
graph
在樹當中只會有一個root value
,也就是樹根,看到下面那張圖7,5,6,9
都有Subtree
(子樹),每個圈圈我們稱它為node
(節點),箭頭稱為edge
,以圖片藍色圈起來的子樹為例,7
就是2, 10, 6
的parent node
,而2, 10, 6
就是7
的children node
。
在樹的資料結構中有許多不同的樹,最常見的樹為二元樹。
二元樹中也有不同種類
(Types of Binary Tree || Designed by Anand K Parmar)
Full Binary Tree
每個節點都有 0 或 2 個子節點
Complete Binary Tree
除了最後一層外,所有層節點都是滿的,在最後一層中,節點盡可能位於左側
Degenerate(or Pathological) Binary Tree
每個父節點只會有一個子節點
Perfect Binary Tree
內部節點都有兩個子節點,並且左右都處於相同深度
Balanced Binary Tree
每個節點的左右子樹的高度最多相差1的二元樹
max heap
就是這次排序中會使用到的資料結構
Complete Binary Tree
SubTree
的 root
一定會是最大
(圖片來自Binary heap)
先將數組轉換成Complete Binary Tree
資料結構,再換成Max Heap
,這時root
值將會是最大值,將root
值移出去,再繼續將樹轉換成Max Heap
,依此類推,這就是堆積排序。
(圖片來源)
首先是建立Max Heap
的pseudo code
heapSize 和 arr 為全域變數,因為在多個function中使用
虛擬碼中,heapSize
的值為數組 arr
的長度减 1
。然後,有一個迴圈從 heapSize / 2
開始,遍歷所有的非葉子節點,至第 0
個節點。
每個非葉子節點會被傳遞給 MAX-HEAPIFY
函數。MAX-HEAPIFY
函數的作用是使其成為max heap
,使得父節點的鍵值都大於等於其子節點的鍵值。
經過這段虛擬碼的執行後,數組 arr
會被轉化成一個max heap
。
這個虛擬碼做的事是在給定的節點i
的子樹中,找到最大的節點並使之成為i
的父節點。
最多走 層,這邊的
n
為node
數量,假設有1024
個node
代表樹為10
層
以下是該虛擬碼的詳細說明:
2,3
行計算i
節點的左右子節點在陣列中的位置。
4,5
行
如果左子節點存在且大於根節點,那麼將左子節點設為最大值。
8,9
行。
如果右子節點存在且大於當前的最大值,那麼將右子節點設為最大值。
10~12
行。如果最大值不是根節點,則交換根節點和最大值並遞迴調用MAX-HEAPIFY(largest
)保持max heap
的性質。
這個 MAX-HEAPIFY
作用是將某一個節點下面的子樹調整成最大堆,並且讓根節點是最大值。
我們舉例arr = [8, 6, 2, 4, 5, 3, 7]
,heapSize
就會等於 6
,接著下來跑迴圈先給予i=3
但arr[3]
底下沒有節點,所以舉i=2
為例子,丟進MAX-HEAPIFY
,接下來往下看
假設i
為 2
,這時候 l = 5
, r = 6
,將虛擬碼帶入數字
這邊可以看到找到最大值的index
等於6
,所以我們跟i
位置的值交換位置,那他會從largest
的位置再往下查看是否為最大值,如果不是就會再持續交換
再來才是本篇重點Heap sort
的pseudo code
,一開始創建max heap
後將最大值與陣列最後一個值互換,這樣就能確保最後一個值為最大值,依照此步驟,依此類推,就可以完成陣列的排序。
如下圖步驟循環
max heap
。(root)
與最後一個節點交換,並將最後一個節點刪除。heap
,使其成為一個max heap
。2
和 3
,直到heap
中只剩下一個節點。Heap Sort
程式碼給你一個整數陣列nums
,請將陣列以升序排列並返回。您必須在O(nlog(n))
時間複雜度內解決此問題,並使用較小的空間複雜度。
@joe94113Tue, JAN 15, 2023 10:00 PM