堆排序是指利用 zhcn 堆；zhtw 堆積；zhhk 堆積； 這種資料結構所設計的一種排序演算法。zhcn 堆；zhtw 堆積；zhhk 堆積； 是一個近似完全二叉樹的結構，並同時滿足堆積的性質：即子節點的鍵值或索引總是小於（或者大於）它的父節點。 概述 若以升序排序說明，把陣列轉換成最大堆積（MaxHeap Heap），這是一種滿足最大堆積性質（MaxHeap Property）的二元樹：對於除了根之外的每個節點 i A parent i A i。 重複從最大堆積取出數值最大的結點（把根結點和最後一個結點交換，把交換後的最後一個結點移出堆），並讓殘餘的堆積維持最大堆積性質。 zhcn 堆；zhtw 堆積；zhhk 堆積； 節點的訪問 通常 zhcn 堆；zhtw 堆積；zhhk 堆積； 是透過一維陣列來實現的。在陣列起始位置為 0 的情形中： 父節點 i 的左子節點在位置 2i1 父節點 i 的右子節點在位置 2i2 子節點 i 的父節點在位置 lfloor i12 rfloor zhcn 堆；zhtw 堆積；zhhk 堆積； 的操作 在 zhcn 堆；zhtw 堆積；zhhk 堆積； 的資料結構中，zhcn 堆；zhtw 堆積；zhhk 堆積； 中的最大值總是位於根節點（在優先佇列中使用 zhcn 堆；zhtw 堆積；zhhk 堆積； 的話 zhcn 堆；zhtw 堆積；zhhk 堆積； 中的最小值位於根節點）。zhcn 堆；zhtw 堆積；zhhk 堆積； 中定義以下幾種操作： 最大 zhcn 堆；zhtw 堆積；zhhk 堆積； 調整（Max Heapify）：將 zhcn 堆；zhtw 堆積；zhhk 堆積； 的末端子節點作調整，使得子節點永遠小於父節點 建立最大 zhcn 堆；zhtw 堆積；zhhk 堆積；（Build Max Heap）：將 zhcn 堆；zhtw 堆積；zhhk 堆積； 中的所有資料重新排序 堆排序（HeapSort）：移除位在第一個資料的根節點，並做最大 zhcn 堆；zhtw 堆積；zhhk 堆積； 調整的遞迴運算 實作範例 C 語言 include stdioh include stdlibh void swap int a int b int temp b b a a temp void max_heapify int arr int start int end 建立父節點指標和子節點指標 int dad start int son dad 2 1 while son end 若子節點指標在範圍內才做比較 if son 1 end arr son arr son 1 先比較兩個子節點大小，選擇最大的 son if arr dad arr son 如果父節點大於子節點代表調整完畢，直接跳出函式 return else 否則交換父子內容再繼續子節點和孫節點比較 swap arr dad arr son dad son son dad 2 1 void heap_sort int arr int len int i 初始化，i 從最後一個父節點開始調整 for i len 2 1 i 0 i max_heapify arr i len 1 先將第一個元素和已排好元素前一位做交換，再重新調整，直到排序完畢 for i len 1 i 0 i swap arr 0 arr i max_heapify arr 0 i 1 int main int arr 3 5 3 0 8 6 1 5 8 6 2 4 9 4 7 0 1 8 9 7 3 1 2 5 9 7 4 0 2 6 int len int sizeof arr sizeof arr heap_sort arr len int i for i 0 i len i printf d arr i printf n return 0 C include iostream include algorithm using namespace std void max_heapify int arr int start int end 建立父節點指標和子節點指標 int dad start int son dad 2 1 while son end 若子節點指標在範圍內才做比較 if son 1 end arr son arr son 1 先比較兩個子節點大小，選擇最大的 son if arr dad arr son 如果父節點大於子節點代表調整完畢，直接跳出函式 return else 否則交換父子內容再繼續子節點和孫節點比較 swap arr dad arr son dad son son dad 2 1 void heap_sort int arr int len 初始化，i 從最後一個父節點開始調整 for int i len 2 1 i 0 i max_heapify arr i len 1 先將第一個元素和已經排好的元素前一位做交換，再從新調整 剛調整的元素之前的元素，直到排序完畢 for int i len 1 i 0 i swap arr 0 arr i max_heapify arr 0 i 1 int main int arr 3 5 3 0 8 6 1 5 8 6 2 4 9 4 7 0 1 8 9 7 3 1 2 5 9 7 4 0 2 6 int len int sizeof arr sizeof arr heap_sort arr len for int i 0 i len i cout arr i cout endl return 0 Java import javautilArrays public class HeapSort private int arr public HeapSort int arr thisarr arr 堆排序的主要入口方法，共兩步。 public void sort 第一步：將陣列堆化 beginIndex 第一個非葉子節點。 從第一個非葉子節點開始即可。無需從最後一個葉子節點開始。 葉子節點可以看作已符合堆要求的節點，根節點就是它自己且自己以下值為最大。 int len arrlength 1 int beginIndex arrlength 1 1 for int i beginIndex i 0 i maxHeapify i len 第二步：對堆化資料排序 每次都是移出最頂層的根節點 A 0，與最尾部節點位置調換，同時遍歷長度 1。 然後從新整理被換到根節點的末尾元素，使其符合堆的特性。 直至未排序的堆長度為 0。 for int i len i 0 i swap 0 i maxHeapify 0 i 1 private void swap int i int j int temp arr i arr i arr j arr j temp 調整索引為 index 處的資料，使其符合堆的特性。 param index 需要堆化處理的資料的索引 param len 未排序的堆（陣列）的長度 private void maxHeapify int index int len int li index 1 1 左子節點索引 int ri li 1 右子節點索引 int cMax li 子節點值最大索引，預設左子節點。 if li len return 左子節點索引超出計算範圍，直接返回。 if ri len arr ri arr li 先判斷左右子節點，哪個較大。 cMax ri if arr cMax arr index swap cMax index 如果父節點被子節點調換， maxHeapify cMax len 則需要繼續判斷換下後的父節點是否符合堆的特性。 測試用例 輸出： 0 0 0 1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 9 9 9 public static void main String args int arr new int 3 5 3 0 8 6 1 5 8 6 2 4 9 4 7 0 1 8 9 7 3 1 2 5 9 7 4 0 2 6 new HeapSort arrsort Systemoutprintln ArraystoString arr Python usrbinenv python codingutf8 def heap_sort lst def sift_down start end 最大堆調整 root start while True child 2 root 1 if child end break if child 1 end and lst child lst child 1 child 1 if lst root lst child lst root lst child lst child lst root root child else break 建立最大堆 for start in range len lst 2 2 1 1 sift_down start len lst 1 堆排序 for end in range len lst 1 0 1 lst 0 lst end lst end lst 0 sift_down 0 end 1 return lst if __name__ __main__ l 9 2 1 7 6 8 5 3 4 heap_sort l JavaScript Arrayprototypeheap_sort function var arr thisslice 0 function swap i j var tmp arr i arr i arr j arr j tmp function max_heapify start end 建立父節點指標和子節點指標 var dad start var son dad 2 1 if son end 若子節點指標超過範圍直接跳出函式 return if son 1 end arr son arr son 1 先比較兩個子節點大小，選擇最大的 son if arr dad arr son 如果父節點小於子節點時，交換父子內容再繼續子節點和孫節點比較 swap dad son max_heapify son end var len arrlength 初始化，i 從最後一個父節點開始調整 for var i Mathfloor len 2 1 i 0 i max_heapify i len 先將第一個元素和已排好元素前一位做交換，再從新調整，直到排序完畢 for var i len 1 i 0 i swap 0 i max_heapify 0 i return arr var a 3 5 3 0 8 6 1 5 8 6 2 4 9 4 7 0 1 8 9 7 3 1 2 5 9 7 4 0 2 6 consolelog aheap_sort PHP php function swap x y t x x y y t function max_heapify arr start end 建立父節點指標和子節點指標 dad start son dad 2 1 if son end 若子節點指標超過範圍直接跳出函式 return if son 1 end arr son arr son 1 先比較兩個子節點大小，選擇最大的 son if arr dad arr son 如果父節點小於子節點時，交換父子內容再繼續子節點和孫節點比較 swap arr dad arr son max_heapify arr son end function heap_sort arr len count arr 初始化，i 從最後一個父節點開始調整 for i ceil len2 1 i 0 i max_heapify arr i len 先將第一個元素和已排好元素前一位做交換，再從新調整，直到排序完畢 for i len 1 i 0 i swap arr 0 arr i max_heapify arr 0 i return arr arr array 3 5 3 0 8 6 1 5 8 6 2 4 9 4 7 0 1 8 9 7 3 1 2 5 9 7 4 0 2 6 arr heap_sort arr for i 0 i count arr i echo arr i Go package main import fmt func HeapSort array int m len array s m2 for i s i 1 i heap array i m1 for i m1 i 0 i array i array 0 array 0 array i heap array 0 i1 func heap array int i end int l 2i1 if l end return n l r 2i2 if r end array rarray ln r if array i array nreturn array n array i array i array n heap array n end func main array int 55 9487143211773942645370129 HeapSort array fmtPrintln array Julia 程式語言 function HeapSort array function adjust lu while true j 2l 左子點 if ju 代表沒有子點 break end if j1 u 有右子點 if array j array j1 j 1 比較左右子點 end end if array j array l 比較父點跟子點 array l array j array j array l l j 有交換 else break 沒交換跳出迴圈 end end end n length array for i in n11 建 max Heap adjust in end 持續把第一個 最大 的元素最後一個交換 array narray 1array 1array n for i in n111 adjust 1i array iarray 1array 1array i end return array end Rust fn max_heapifyT Ord Copydata mut T pos usize end usize let mut dad pos let mut son dad 2 1 while son end if son end data son data son 1 son 1 if data dad data son return else dataswap dad son dad son son dad 2 1 fn heap_sortTOrdCopydata mut T let len datalen for i in 0len 2 1rev max_heapify data i len 1 for i in 1len 1rev dataswap 0 i max_heapify data 0 i 1 fn main let mut nums vec9 2 1 7 6 8 5 3 4 heap_sort numsas_mut_slice 原地堆排序 基於以上 zhcn 堆；zhtw 堆積；zhhk 堆積； 相關的操作，我們可以很容易的定義堆排序。例如，假設我們已經讀入一系列資料並建立了一個 zhcn 堆；zhtw 堆積；zhhk 堆積；，一個最直觀的演算法就是反覆的呼叫 del_max 函式，因為該函式總是能夠返回 zhcn 堆；zhtw 堆積；zhhk 堆積； 中最大的值，然後把它從 zhcn 堆；zhtw 堆積；zhhk 堆積； 中刪除，從而對這一系列返回值的輸出就得到了該序列的降序排列。真正的原地堆排序使用了另外一個小技巧。堆排序的過程是： 建立一個 zhcn 堆；zhtw 堆積；zhhk 堆積； H 0n1 把 zhcn 堆；zhtw 堆積；zhhk 堆積； 首（最大值）和 zhcn 堆；zhtw 堆積；zhhk 堆積； 尾互換 把 zhcn 堆；zhtw 堆積；zhhk 堆積； 的尺寸縮小 1，並呼叫 shift_down 0 目的是把新的陣列頂端資料調整到相應位置 重複步驟 2，直到 zhcn 堆；zhtw 堆積；zhhk 堆積； 的尺寸為 1 平均複雜度 堆排序的平均時間複雜度為 Omicron n log n，空間複雜度為 Theta 1。 參考 外部連結 常見排序演算法 堆排序 Heap Sort 堆演算法的視覺化演示 可以直觀看到堆演算法的操作 Category 排序演算法 Category 帶有程式碼示例的條目 noSorteringsalgoritmeHeap sort