參考來自:堆排序及分析
package sort.algorithm.heap;
public class Heap
{
// 堆排序,它組合了歸併排序的時間效率和快速排序的控件效率。和歸併排序一樣,堆排序
// 的最差情況運行時間爲O(nlogn),和快速排序一樣它不需要額外的數組
public static void heapsort(int[] data, int n)
{
int unsorted; // 數組中未排序部分的大小
int temp; // 在交換兩個數組位置時使用
makeHasp(data, n);
unsorted = n;
show(data);
while (unsorted > 1)
{
unsorted--;
temp = data[0];
data[0] = data[unsorted];
data[unsorted] = temp;
show(data);
reheapifDown(data , unsorted);
}
}
// 向下堆重排
// data中的值重新排列了,使得data的前n個元素現在形成了堆
// 通過持續地交換不協調元素和它的最大孩子節點起作用的。
private static void reheapifDown(int[] data, int nlength)
{
int current; // 要往下移動的節點的下標
int bigChiledIndex; // 當前節點的孩子中,較大一個的下標
boolean heapOkey; // 當堆正確時爲true
current = 0;
heapOkey = false;
// 當不協調元素到達葉子節點或不協調元素大於他的兩個孩子時,交換停止
while ((!heapOkey)&&((current*2 + 1) < nlength))
{
// 將bigChiledIndex設置爲current節點的孩子中較大結點的下標
if ((2*current+2) < nlength )
{
if (data[current*2 +1] > data[current*2 +2])
{
bigChiledIndex = current*2+1;
}else {
bigChiledIndex = current*2+2;
}
} else {
// 如果只有一個節點那麼bigChildIndex將被設置成這個孩子的下標
bigChiledIndex = current*2+1;
}
if (data[current] < data[bigChiledIndex])
{
System.out.println("*"+data[current]+","+data[bigChiledIndex]);
int temp = data[current];
data[current] = data[bigChiledIndex];
data[bigChiledIndex] = temp;
current = bigChiledIndex;
} else {
heapOkey = true;
}
show(data);
}
}
// 向上堆重排(data中的元素已經重新排列,是的由數組表示的完全二叉樹成爲堆)
private static void makeHasp(int[] data, int n)
{
int i,k;
int temp;
for (i = 1;i < n;i++)
{
k = i;
// data[k]還不是跟,data[k]比它的雙親大
while (k != 0 && data[k] > data[parent(k)])
{
temp = data[k];
data[k] = data[parent(k)];
data[parent(k)] = temp;
k = parent(k);
}
}
}
// k節點的雙親節點的下標
private static int parent(int k)
{
return (k-1)/2;
}
public static void show(int[] data)
{
for (int i = 0; i < data.length; i++)
{
System.out.print(data[i] + ",");
}
System.out.println();
}
public static void main(String[] args)
{
int data[] = {80, 30, 60, 50, 40, 70, 20, 10, 5, 0};
heapsort(data,10);
show(data);
}
}