思路:
- 把数组构建成二叉堆;
- 大根堆根节点为最大值,删除根节点,堆大小减一,把删除的元素放在空出来的堆数组位置,即把最大值放在了数组的末尾;
- 重复删除根节点,即找到了第二大、第三大…的元素,直到堆的长度减小到0,即可实现堆排序,时间复杂度为O(N log N);
- 用大根堆实现从小到大排序,用小根堆实现从大到小排序。
package com.mindle.heap;
import java.util.Arrays;
public class HeapSort<AnyType extends Comparable<? super AnyType>> {
public static final int UP = 0; // 从小到大排序
public static final int DOWN = 1; // 从大到小排序
/**
* 用堆排序算法将数组排序
*
* @param array
* 数组
* @param size
* 数组大小
* @param mode
* 排序顺序
*/
public void heapSort(AnyType[] array, int size, int mode) {
switch (mode) {
case UP:
buildHeap1(array, size);
for (int i = size; i > 0; i--)
deleteMax(array, i);
break;
case DOWN:
buildHeap2(array, size);
for (int i = size; i > 0; i--)
deleteMin(array, i);
break;
default:
break;
}
}
/**
* 大根堆的下滤
*
* @param array
* 数组
* @param size
* 数组大小
* @param index
* 下滤元素的索引号
*/
private void percolateDown1(AnyType[] array, int size, int index) {
AnyType temp = array[index];
int child;
for (; index <= size / 2 - 1; index = child) {
child = index * 2 + 1; // 左孩子
if (child != size - 1 && array[child + 1].compareTo(array[child]) > 0)
child++;
if (array[child].compareTo(temp) > 0)
array[index] = array[child];
else
break;
}
array[index] = temp;
}
/**
* 小根堆的下滤
*
* @param array
* 数组
* @param size
* 数组大小
* @param index
* 下滤元素的索引号
*/
private void percolateDown2(AnyType[] array, int size, int index) {
AnyType temp = array[index];
int child;
for (; index <= size / 2 - 1; index = child) {
child = index * 2 + 1; // 左孩子
if (child != size - 1 && array[child + 1].compareTo(array[child]) < 0)
child++;
if (array[child].compareTo(temp) < 0)
array[index] = array[child];
else
break;
}
array[index] = temp;
}
/**
* 删除大根堆的根元素,把删除的元素放到堆数组的末尾
*
* @param array
* 数组
* @param size
* 数组大小
* @return
*/
private AnyType deleteMax(AnyType[] array, int size) {
AnyType maxItem = array[0];
array[0] = array[--size];
array[size] = maxItem;
if (size != 0)
percolateDown1(array, size, 0);
return maxItem;
}
/**
* 删除小根堆的根元素,把删除的元素放到堆数组的末尾
*
* @param array
* 数组
* @param size
* 数组大小
* @return
*/
private AnyType deleteMin(AnyType[] array, int size) {
AnyType minItem = array[0];
array[0] = array[--size];
array[size] = minItem;
if (size != 0)
percolateDown2(array, size, 0);
return minItem;
}
/**
* 构建大根堆堆
*
* @param array
* 数组
* @param size
* 数组大小
*/
private void buildHeap1(AnyType[] array, int size) {
for (int i = size / 2 - 1; i >= 0; i--)
percolateDown1(array, size, i);
}
/**
* 构建小根堆
*
* @param array
* 数组
* @param size
* 数组大小
*/
private void buildHeap2(AnyType[] array, int size) {
for (int i = size / 2 - 1; i >= 0; i--)
percolateDown2(array, size, i);
}
// 测试
public static void main(String[] args) throws Exception {
Integer[] data = { 7, 8, 9, 4, 6, 1, 2, 3, 5, 17, 14, 11, 12, 15, 18, 13, 16, 19 };
System.out.println(Arrays.toString(data));
HeapSort<Integer> heapSort = new HeapSort<>();
heapSort.heapSort(data, data.length, DOWN);
System.out.println(Arrays.toString(data));
heapSort.heapSort(data, data.length, UP);
System.out.println(Arrays.toString(data));
}
}