要求:从小到大排序
思路:先将数组构建成大顶堆, 然后依次“删除”顶部元素 到末尾
/**
* “下沉”操作 ,如果构建大顶堆,将小的下沉;如果构建小顶堆,将大的下沉;这里是将小的下沉
* 由于从底部开始调整,,下面的已经是大顶堆了
* @param array 待调整的数组(堆)
* @param parentIndex 父节点
* @param lastIndex 最大位置
*/
public static void downAdjust(int[] array,int parentIndex,int lastIndex){
// 保存父节点的值,用于进行最后的替换你
int tmp=array[parentIndex];
// 获取子节点位置
int biggerChildIndex=2*parentIndex+1;
while (biggerChildIndex<=lastIndex){
// 看一下左右子节点那个更大,将biggerChildIndex指向更大那个
if(biggerChildIndex+1<lastIndex&&array[biggerChildIndex+1]>array[biggerChildIndex]){
biggerChildIndex++;
}
// 看一下父节点是否需要下沉
if(tmp>=array[biggerChildIndex]){
// 如果父节点较大,说明已经是大顶堆,跳出循环,不需要调整
break;
}
// 大的上浮
array[parentIndex]=array[biggerChildIndex];
// 继续往下调整,更新指标
parentIndex=biggerChildIndex;
biggerChildIndex=2*parentIndex+1;
}
// 进行最后的替换
array[parentIndex]=tmp;
}
/**
* 进行堆排序
* @param array 待排序的数组
*/
public static void heapSort(int [] array){
// 先将数组构建成大顶堆
int lastIndex=array.length-1;
// 从下往上调整
for(int i=(lastIndex-1)/2;i>=0;i--){
downAdjust(array,i,lastIndex);
}
// 进行堆排序 -- 不断将大顶堆的顶部 “删除”,不断换新的最大元素上来
for(int curLastIndex=array.length-1;curLastIndex>0;curLastIndex--){
// 将当前最大的顶部元素取出来
int tmp=array[curLastIndex];
array[curLastIndex]=array[0];
array[0]=tmp;
// 调整堆,获取新的大顶堆
downAdjust(array,0,curLastIndex-1);
}
}
fun heapSort(array: Array<Int>) {
val len = array.size
if (len <= 1) {
return
}
var lastIndex = len - 1
//1、先进行一次构建大顶堆操作 -- 下潜
//1.1 构建大顶堆的方法是: 确定每一个节点下面的堆都是大顶堆
for (i in lastIndex / 2..0) {
val curTopIndex = i // 需要让curTopIndex为顶点的堆是大顶堆
buildBigTopHeap(array, curTopIndex, lastIndex)
}
//2、每次将最大的放到最后一位,然后以此末尾为界限进行大顶堆构建操作
while (lastIndex > 0) {
//将顶部的数字和当前最末值交换
val tmp = array[lastIndex]
array[lastIndex] = array[0]
array[0] = tmp
lastIndex--
buildBigTopHeap(array, 0, lastIndex)
}
}
/**
* 构建以curTopIndex为顶点的大顶堆,由于是从最底下开始构建,可以确保下面的已经是大顶堆了
* 需要找到最大的子节点,看需不需要调整
*/
fun buildBigTopHeap(array: Array<Int>, curTopIndex: Int, lastIndex: Int) {
var parentIndex = curTopIndex
var maxChildIndex = parentIndex * 2 + 1
val topValue = array[curTopIndex]
//找到当前顶点应该下潜到的位置
while (maxChildIndex <= lastIndex) {
//看一下右子节点会不会是最大的子节点
if (maxChildIndex + 1 <= lastIndex && array[maxChildIndex + 1] > array[maxChildIndex]) {
maxChildIndex += 1
}
//看一下是否需要父节点是否需要调整
if (topValue >= array[maxChildIndex]) {
break
}
//进行调整
array[parentIndex] = array[maxChildIndex]
//array[maxChildIndex] = topValue -- 由于topValue需要不断下潜,可以暂时不赋值,直接比较
//继续
parentIndex = maxChildIndex
maxChildIndex = 2 * parentIndex + 1
}
array[parentIndex] = topValue
}