最大堆的性质:
A[i]>=A[2*i] && A[i] >=A[2*i+1] i=1,2,…n/2
满足这种关系的二叉树就叫做最大堆。
利用最大堆实现排序的原理
最大的特点是根节点的值是所有节点中值最大的节点。利用这个特点就可以通过不断将根节点交换到尾部的有序数组内就可以实现堆排序。
1.构建最大堆
2.将根节点与未排序部分的最后一个元素交换
3.调整堆,使得堆重新变为最大堆
时间复杂度
调整最大堆的函数AdjustHeap的复杂度是log(n)
通过交换堆的最大值到尾部的来构造有序数组的操作的复杂度是n
所以堆排序的时间复杂度是:n*log(n)
代码实现:
public class HeapSortDemo {
private static int HeapSize;
public static void main(String[] args) {
int A[] = new int[]{1,2 ,3,4,7,8,9,10,14,16};
heapSort(A);
for (int i : A) {
System.out.println(i);
}
}
public static void heapSort(int x[]){
HeapSize=x.length;
buildMaxHeap(x);
for (int i : x) {
System.out.println("build:"+i);
}
int tmp;
for(int i=x.length-1;i>0;--i){
tmp=x[i];
x[i]=x[0];
x[0]=tmp;
HeapSize--;
AdjustHeap(x,0);
}
}
public static void buildMaxHeap(int[] x) {
// n/2+1... n-1之间到叶节点不需要调整
//从叶节点开始自底向上构造最大堆
for (int i = x.length / 2-1; i >= 0; --i) {
AdjustHeap(x, i);
}
}
//调整以x[i]为根节点的树
public static void AdjustHeap(int[] x, int i) {
i++;
int l = i * 2 ;
int r = i * 2+ 1;
l--;
r--;
i--;
int largest = i;
if (r < HeapSize && x[r] > x[largest]) {
largest = r;
}
if (l < HeapSize && x[l] > x[largest]) {
largest = l;
}
if(largest!=i){
int tmp = x[i];
x[i] = x[largest];
x[largest] = tmp;
AdjustHeap(x,largest);
}
}
}