堆排序
堆排序是一种原地排序算法,在任何时候,数组只有常数个元素存储在输入数组以外。
堆排需要用到堆,堆是一种数据结构,它可以被视为一棵完全二叉树,树中每个节点与数组中存放给节点的值对应。
由二叉树的性质,我们可以知道父节点下标为i/2,左子树节点为2i,右子树节点为2i+1.
二叉堆有两种,分为最大堆和最小堆。最大堆是指除根节点外,所有父节点都大于或等于其子节点。最大堆的最大元素存放在根节点。
最小堆则与最大堆相反,最小堆的最小元素在根节点。
在堆排序中,我们通常使用最大堆,最小堆通常在构造优先队列时使用。堆可以被看做是一棵树。具有n个元素的堆是基于一棵完全二叉树,
其高度为log2 n.
在构建最大堆的过程中,我们要保持最大堆的性质,即父节点大于或等于其子节点,时间复杂度为O(log2 n).
java实现
public class Heap_Sort{
public int heapSize;
public static void main(String[] args){
int[] unsorted = new int[]{3,3,2,1,7,4,5,9};
builtMaxHeap(unsorted);
for(int i = unsorted.length-1; i >= 1;i--){
int tmp = unsorted[i];
unsorted[i] = unsorted[1];
unsorted[1] = tmp;
heapSize = heapSize-1;
maxHeap(unsorted,1);
}
}
private static builtMaxHeap(int[] unsorted){//建堆
heapSize = unsorted.length;
int len = unsorted.length;
for(int i = len/2; i >= 0; i--){
maxHeap(unsorted,i);
}
}
private static maxHeap(int[] unsorted,int i){ //使堆保持根节点最大
int l = 2*i;//左子树下标
int r = 2*i+1;//右子树下标
int largest = i;
if(l <= heapSize&&unsorted[l] > unsorted[i]){ //如果左子节点大于其父节点,最大下标为l,否则为i
largest = l;
}else{
largest = i;
}
if(r <= heapSize&&unsorted[r] > unsorted[]largest){ //如果右子节点大于最大值,largest = r;
largest = r;
}
if(largest != i){ //如果其父节点不是最大值,交换,使其保持最大堆的性质
int tmp = unsorted[largest];
unsorted[largest] = unsorted[i];
unsorted[i] = tmp;
maxHeap(unsorted,largest);//递归调用
}
}
}
时间复杂度:O(nlog2 n)