需求分析:要求将给定的无序数组有序化
思路:循环删除堆顶元素,直到堆空,将堆顶元素记录到结果数组中
remove函数:删除并返回堆顶元素(用array[lastIndex]覆盖array[0],再将array[lastIndex]赋值为0,并下滤array[0]).
方法:
static int lastIndex;
public static int[] heapSort2(int[] array){
int[] result = new int[array.length];
int cnt = array.length;
int j = 0;
heapify(array); //批量建堆
lastIndex = array.length-1;
while(cnt-- > 0){
result[j++] = remove(array);
}
return result;
}
public static void siftDown(int index, int[] array) {
int element = array[index];
int half = array.length >> 1;
// 第一个叶子节点的索引 == 非叶子节点的数量
// index < 第一个叶子节点的索引
// 必须保证index位置是非叶子节点
while (index < half) {
// index的节点有2种情况
// 1.只有左子节点
// 2.同时有左右子节点
// 默认为左子节点跟它进行比较
int childIndex = (index << 1) + 1;
int child = array[childIndex];
// 右子节点
int rightIndex = childIndex + 1;
// 选出左右子节点最大的那个
if (rightIndex < array.length && array[rightIndex] > child) {
child = array[childIndex = rightIndex];
}
if (element >= child) break;
// 将子节点存放到index位置
array[index] = child;
// 重新设置index
index = childIndex;
}
array[index] = element;
}
/**
* 批量建堆
* @param array
* @param
*/
//自下而上的下滤
public static void heapify(int[] array){
for (int i = (array.length >>1) - 1; i >= 0; i--){
siftDown(i,array);
}
}
/*
删除堆顶元素,并返回
*/
public static int remove(int[] array){
emptyCheck(array);
int rtn = array[0];
array[0] = array[lastIndex];
array[lastIndex] = 0;
lastIndex--;
siftDown(0,array);
return rtn;
}
public static void emptyCheck(int[] array){
if (array.length == 0){
throw new IndexOutOfBoundsException("Heap is empty");
}
}
主函数:
public static void main(String[] args){
int[] arr = {1,3,5,2,4,7,8};
System.out.println(Arrays.toString(heapSort2(arr)));
}
运行结果: