堆排序八大排序算法之一。
堆排序是指利用堆积树(堆)这种 数据结构所设计的一种排序算法,它是选择排序的一种。
堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:
Key[i] <= key[2i+1] && Key[i] <= key[2i+2] 或者
Key[i] >= Key[2i+1] && key>=key[2i+2]
即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。堆分为大顶堆和小顶堆,
满足 Key[i] >= Key[2i+1] && key >= key[2i+2] 称为大顶堆,
满足 Key[i] <= key[2i+1] && Key[i] <= key[2i+2] 称为小顶堆。
由上述性质可知大顶堆的堆顶的关键字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。
小顶堆排序的过程:
(1)从最后一个非叶子节点开始,每三个节点做一次大小比较,最小的做根,如果移动过程中如果子树上的顺序被破坏了,子树上重新调整三个节点的位置。
(2)取走整个树的根节点,把最后一个叶子作为根节点。
(3)重复(1)和(2)的过程,知道树中的所有节点全部被取走为止。
public static void heapSort(int[] array){
int n = array.length; //堆中元素的个数
//对整个数组建堆,从最后一个非叶子节点(array.length-1)/2开始建堆,一直到根节点
for(int i=(array.length-1)/2;i>=0;i--){
createHeap(array,n,i);
}
while (n>0){
System.out.print(array[0]+" "); //输出根节点
array[0] = array[n-1]; //把最后一个节点放到根节点上
n--;
createHeap(array,n,0); //从根节点开始重新建堆
}
}
public static void createHeap(int[] array,int n,int k){
int kLeft = 2*k + 1; //k的左孩子的下标
int kRight = 2*k + 2; //k的右孩子的下标
if(kLeft>=n && kRight>=n){ //如果两个下标都越界,表示没有左右孩子
return;
}
int kLeftValue = Integer.MAX_VALUE; //如果是最大值,代表没有左孩子
int kRightValue = Integer.MAX_VALUE;
if(kLeft<n){
kLeftValue = array[kLeft];
}
if(kRight<n){
kRightValue = array[kRight];
}
//对三个节点比较大小
if(array[k]<kLeftValue && array[k]<kRightValue){ //如果左右孩子都比k小,则不用建堆,直接返回
return;
}
if(kLeftValue < kRightValue){ //如果左孩子比右孩子小,就用左孩子和k交换
int temp = array[k];
array[k] = array[kLeft];
array[kLeft] = temp;
createHeap(array,n,kLeft); //为了防止交换数字后破坏树中的堆结构,必须要重新建堆
}else{
int temp = array[k];
array[k] = array[kRight];
array[kRight] = temp;
createHeap(array,n,kRight);
}
}
堆排序应用场景:当数据为无序或链式结构的时候进行二分查找。一般不用来排序,安卓代码用不到,使用在大数据的查找,一般写在后台, 虽然不常用但是我们还是应该了解一下的。