堆排序(heapsort)是指利用堆積樹(堆)這種資料結構所設計的一種排序演算法,它是選擇排序的一種。可以利用陣列的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即a[parent[i]] >= a[i]。在陣列的非降序排序中,需要使用的就是大根堆,因為根據大根堆的要求可知,最大的值一定在堆頂。
堆的定義
乙個完全二叉樹中,任意父結點總是大於或等於(小於或等於)任何乙個子節點,則為大頂堆(小頂堆)。
完全二叉樹適合採用順序儲存的方式,因此乙個陣列可以看成乙個完全二叉樹。
從乙個結點的編號就可推得其雙親,左、右孩子,兄弟等結點的編號。假設編號為i的結點是ki(1≤i≤n),則有:
①若i>1,則ki的雙親編號為i/2;若i=1,則ki是根結點,無雙親。
②若2i≤n,則ki的左孩子的編號是2i;否則,ki無左孩子,即ki必定是葉子。因此完全二叉樹中編號i>n/2的結點必定是葉結點。
③若2i+1≤n,則ki的右孩子的編號是2i+1;否則,ki無右孩子。
注:ki(0≤i≤n)滿足陣列下標時,則可能的左右孩子分別為2i+1、2i+2。
利用堆頂記錄的是最大關鍵字這一特性,每一輪取堆頂元素放入有序區,就類似選擇排序每一輪選擇乙個最大值放入有序區,可以把堆排序看成是選擇排序的改進。
將初始待排序關鍵字序列(r0,r1,r2....rn)構建成大頂堆,此堆為初始的無序區;
將堆頂元素r[0]與最後乙個元素r[n]交換,此時得到新的無序區(r0,r1,r2,......rn-1)和新的有序區(rn);
由於交換後新的堆頂r[0]可能違反堆的性質,因此需要對當前無序區(r0,r1,r2,......rn-1)調整為新堆。
不斷重複此2、3步驟直到有序區的元素個數為n-1,則整個排序過程完成。
演算法分析
//最難理解的地方
如下圖:
2.初始化堆
從最後乙個非葉子節點i
(i=n/2,n為節點個數)開始,將以i為根節點的二叉樹通過篩選調整為堆。以第一張圖為例,編號順序為8、7、6...1。
從最後乙個非葉子節就保證了篩選演算法的正確性,因為篩選演算法的目標是乙個所有子樹都為堆的完全二叉樹。
php實現堆排序:
<?php
//堆排序,對簡單排序的改進
function swap(array &$arr,$a,$b)
//調整$arr[$start]的關鍵字,$arr[$start]、$arr[$start+1]、、、$arr[$end]成為乙個大根堆(根節點最大的完全二叉樹)
//注意:這裡節點s的左右孩子是 2*s +1 和 2*s+2(陣列開始下標為0時)
function heapadjust(array &$arr $start $end)
if ($temp >=$arr[$j])
//將根節點設定為子節點的較大值
$arr[$start]=$arr[$j];
//繼續往下
$start=$j;
}$arr[$start] =$temp;
}function heapsort(array &$arr)
for ($i=$count-1; $i >=0 ; $i--)
}$arr=array(4,1,5,9);
heapsort($arr);
var_dump($arr);
?>
堆排序簡單實現
演算法導論排序演算法部分第乙個就介紹堆排序,也得複習複習。wiki 上也有介紹及 實現,基本上都是一樣的。摘錄堆排序定義如下 堆排序 heapsort 是指利用堆這種資料結構所設計的一種排序演算法。堆是乙個近似完全二叉樹的結構,並同時滿足堆性質 即子結點的鍵值或索引總是小於 或者大於 它的父節點。然...
簡單的堆排序
堆排序的是先建立乙個完全二叉樹,之後調整成乙個大頂堆,再進行堆調整的過程!include include 時間函式 include using namespace std int h 101 用來存放堆的陣列 int n 用來儲存堆中元素的個數,也就是堆的大小 void swap int x,int...
堆排序《一》 簡單結構堆排序
堆排序 利用最大堆 最小堆完成排序 用陣列儲存,但邏輯結構為 完全二叉樹 heapelem arr 物理結構 邏輯結構 i 3 要調整的結點 j i 2 1 左孩子結點 對 3 7 8 進行判斷,已符合最小堆規則 則不調整 break arr i tmp pos 開始迴圈調整 2位置的 while ...