参考来自:堆排序及分析
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);
}
}