原理:
(首先你需要了解二叉堆的概念,知道先序遍历,什么叫最大树、最小树,父子节点的下标计算,如何实现最大小树
)其实就是在你构建好最大树(这里面以最大树为例子),拿到头结点(一定是这个队列里面的最大值),把他放在数组的最后面,他前面的数值一定比这个数大。然后缩小范围,将前面的数重新构建为最大树,再拿出根节点,直到剩最后一个值。这样就变为有序的数组。
图示:
代码实现:
public class HeapSort {
public void maxHeapDown(int[] arr,int start,int end){
int l = start*2+1;//得到待排序树的根节点的左子树节点
int c = start; //指向当前节点
int temp = arr[start];
for(;l<end;c=l,l=c*2+1){//同时这个循环是担心替换之后,对于之前的已经生成的最大树造成影响
//当然如果是最初始状态,这两个子节点也是叶子节点就跟不需要调整了
//那个节点没有替换,就不需要重新调整
if(arr[l]<arr[l+1])
l++;//因为是中序遍历,所以l+1就是右子节点
if(temp>=arr[l]) break;
else {
arr[c] = arr[l];
arr[l] = temp;
}
}
}
public void HeapSort(int[] arr, int n){
for(int i= n/2-1;i>=0;i--){
maxHeapDown(arr,i,n-1);
}
for(int i=n-1;i>0;i--){
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
maxHeapDown(arr,0,i-1);
}
}
public static void main(String[] args) {
int a[] = {20,30,90,40,70,110,60,10,100,50,80};
new HeapSort().HeapSort(a,a.length);
System.out.println(Arrays.toString(a));
}
}
时间复杂度
堆排序的时间复杂度是O(N * lgN)。
假设被排序的数列中有N个数。遍历一趟的时间复杂度是O(N),需要遍历多少次呢?
堆排序是采用的二叉堆进行排序的,二叉堆就是一棵二叉树,它需要遍历的次数就是二叉树的深度,而根据完全二叉树的定义,它的深度至少是lg(N+1)。最多是多少呢?由于二叉堆是完全二叉树,因此,它的深度最多也不会超过lg(2N)。因此,遍历一趟的时间复杂度是O(N),而遍历次数介于lg(N+1)和lg(2N)之间;因此得出它的时间复杂度是O(N * lgN)。
堆排序是不稳定的算法