堆排序:一種基於堆的排序算法;
一些基礎概念
堆定義:
當且僅當該序列滿足如下性質(簡稱爲堆性質):
(1) ki≤K2i且ki≤K2i+1 或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ n) //ki相當於二叉樹的非葉結點,K2i則是左孩子,k2i+1是右孩子
若將此序列所存儲的向量R[1..n]看做是一棵完全二叉樹的存儲結構,則堆實質上是滿足如下性質的完全二叉樹:
樹中任一非葉結點的關鍵字均不大於(或不小於)其左右孩子(若存在)結點的關鍵字。
下圖爲數組對應的大根堆和小根堆。
堆的高度:
堆可以被看成是一棵樹,結點在堆中的高度可以被定義爲從本結點到葉子結點的最長簡單下降路徑上邊的數目;定義堆的高度爲樹根的高度。我們將看到,堆結構上的一些基本操作的運行時間至多是與樹的高度成正比,爲O(lgn)
大根堆的堆排序思想:
1) 初始化R[1…n]爲大根堆,該堆爲無序的;
2) 交換R[1]和R[n],R[1…n-1]爲無序的,R[n]爲有序的;
3) 初始化R[1…n-1]爲大根堆;
4) 交換R[1]和R[n-1],R[1…n-2]爲無序的,R[n-1…n]爲有序的;
依次重複,知道排好序爲止。
算法如下:
/**
* 建立堆
* heap爲需要建堆的數組,
* root建堆的起始根
* index爲未排序的最後葉子節點
*/
private static void createHeap(int[] heap, int root, int index) {
int left;
int right;
int tmp;
if(root>=index){
return ;
}
while (root >= 0) {
left = root << 1;
right = (root << 1) + 1;
if (right <= index) {
if (heap[root] < heap[right]) {
tmp=heap[root];
heap[root]= heap[right];
heap[right]=tmp;
createHeap(heap, right, index);
}
}
if (left <= index) {
if (heap[root] < heap[left]) {
tmp=heap[root];
heap[root]= heap[left];
heap[left]=tmp;
createHeap(heap, left, index);
}
}
root–;
}
}
public static void heapSort(int[]heap, int index) {
int i, j, Temp;
// 將二叉樹轉成Heap
for (i = (index / 2); i >= 1; i–)
createHeap(heap,i, index);
// 開始進行堆排序
for (i = index ; i >= 1; i–) {
Temp = heap[i]; // Heap的Root值和最後一個值交換
heap[i] = heap[0];
heap[0] = Temp;
createHeap(heap,0, i-1); // 對其餘數值重建堆
System.out.print(“排序中: “);
for (j = 0; j <= index; j++)
System.out.printf(“%3s”, heap[j]);
System.out.println(“”);
}
}