堆可以視為一棵完全的二叉樹,除了最底層之外,每一層都是滿的,這使得堆可以利用數組來表示,每一個結點對應數組中的一個元素。
數組與堆之間的關係:
二元堆積一般分為兩種:最大堆和最小堆。
最大堆:堆中每個父節點的元素值都大於等於其孩子結點(如果存在);
最小堆:堆中每個父節點的元素值都小於等於其孩子結點(如果存在);
什麼是堆排序
堆排序(假設利用最大堆)就是把堆頂的最大數取出,將剩餘的堆繼續調整為最大堆
堆排序演算法
建堆:建堆是不斷調整堆的過程,從 len/2 處開始調整,一直到第一個節點,此處 len 是堆中元素的個數。建堆的過程是線性過程,從 len/2 到 0 處一直調用調整堆的過程,相當於 o(h1) + o(h2) …+ o(hlen/2) 其中 h 表示節點的深度,len/2 表示節點的個數,這是一個求和的過程,結果是線性 O(n)。
調整堆:調整堆在構建堆的過程中會用到,而且在堆排序過程中也會用到。利用的思想是比較節點i和它的孩子節點 left(i) , right(i),選出三者最大(或者最小)者,如果最大(小)
值不是節點i而是它的一個孩子節點,那邊互動節點i和該節點,然後再調用調整堆過程,這是一個遞迴的過程。調整堆的過程時間複雜度與堆的深度有關係,是 logn 的操作,因
為是沿著深度方向進行調整的。
堆排序:堆排序是利用上面的兩個過程來進行的。首先是根據元素構建堆。然後將堆的根節點取出(一般是與最後一個節點進行交換),將前面 len-1 個節點繼續進行堆調整的過
程,然後再將根節點取出,這樣一直到所有節點都取出。堆排序過程的時間複雜度是 O(nlogn)。因為建堆的時間複雜度是 O(n)(調用一次);調整堆的時間複雜度是 logn,調
用了 n-1 次,所以堆排序的時間複雜度是O(nlogn)。
例子:
<?php// PHP 堆排序演算法實現、堆排序時間複雜度分析/** * 堆排序 * @param array $arr */function heap_sort(array &$arr){ $count = count($arr); // 建堆 (下標小於或等於floor($count/2)-1的節點都是要調整的節點) for($i = floor($count / 2) - 1; $i >= 0; $i --) { heap_adjust($arr, $i, $count); } // 調整堆 for($i = $count - 1; $i >= 0; $i--) { //將堆頂元素與最後一個元素交換 swap($arr,0,$i); heap_adjust($arr,0,$i - 1); }}/** * 交換2個值 * @param array $arr * @param int $a 數組下標 * @param int $b 數組下標 */function swap(array &$arr, $a, $b){ $temp = $arr[$a]; $arr[$a] = $arr[$b]; $arr[$b] = $temp;}/** * 交換2個值 * @param array $arr * @param int $start 數組下標 * @param int $end 數組下標 */function heap_adjust(array &$arr, $start, $end){ $temp = $arr[$start]; //沿關鍵字較大的孩子節點向下篩選,這裡數組開始下標識0 for($j = 2 * $start + 1; $j <= $end; $j = 2 * $j + 1) { if($j != $end && $arr[$j] < $arr[$j + 1]) { $j ++; } if($temp < $arr[$j]) { //將根節點設定為子節點的較大值 $arr[$start] = $arr[$j]; $start = $j; } } $arr[$start] = $temp;}// 使用$arr = array(8,4,2,9,3,7,1,6,5);heap_sort($arr);print_r($arr);
輸出:
Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 [8] => 9 )
時間複雜度分析
總體上來說,堆排序的時間複雜度是 O(nlogn)。由於堆排序對原始記錄的排序狀態並不敏感,因此它無論是最好、最差和平均時間複雜度都是 O(nlogn)。這在效能上顯然要遠遠好於冒泡、簡單選擇、直接插入的 O(n^2) 的時間複雜度了。
堆排序是一種不穩定排序方法(排序前後相同元素的前後順序可能改變)。
相關推薦:
JavaScript中的堆排序詳解
PHP排序演算法之堆排序詳解
PHP堆排序演算法執行個體詳解