堆排序(HeapSort)是利用完全二叉树特性的一种选择排序。
定义如下:
设n个元素的数据序列{K0,k1,k2,...,kn-1},当且仅当满足下列关系时,称为最小/大堆。Ki<=K2i+1且Ki<=K2i+2或Ki>=K2i+2,i=0,1,2,...,[n/2-1]换言之,将{{K0,K1,...,Kn-1}}序列看成是一棵完全二叉树的层次遍历序列,如果任意一个结点元素<=/>=其孩子结点元素,则称该序列为最小/大堆,根结点值最小/大。
堆排序简单说来就是:将一个数据序列建成最小/大堆,则根结点值最小/大。
代码实现如下:
package g;
public class HeapSort {
public static int[] randomInt(int n, int size) {
int[] value = new int[n];
for (int i = 0; i < value.length; i++) {
value[i] = (int) (Math.random() * size);
}
return value;
}
public static void print(int[] keys) {
for (int i : keys) {
System.out.print(i + " ");
}
System.out.println();
}
public static void swap(int[] keys, int i, int j) {
int temp = keys[i];
keys[i] = keys[j];
keys[j] = temp;
}
// 将keys数组中以parent为根的子树调整成最小/大堆,子序列范围为parent~end
// 私有方法,只被堆排序方法调用,确保parent、end在范围内
public static void sift(int[] keys, int parent, int end, boolean minheap) {
System.out.print("sift " + parent + ".." +end+ "\t");
// child是parent的左孩子,因为根据二叉树性质5,完全二叉树中的第i(0<=i<n)个结点,如果有孩子
// 则左孩子为第2i+1个结点,右孩子为第2i+2个结点
int child = 2 * parent + 1;
int value = keys[parent];
// 沿较小/大值孩子结点向下筛选
while (child <= end) {
if (child < end && (minheap ? keys[child] > keys[child + 1] : keys[child] < keys[child + 1])) {
// child记住孩子值较小/大者
child++;
}
// 若父母结点值较小/大
if (minheap ? value > keys[child] : value < keys[child]) {
// 将较小/大孩子结点值上移
keys[parent] = keys[child];
// parent、child两者都向下一层
parent = child;
child = 2 * parent + 1;
} else {
break;
}
}
// 当前子树的原根值调整后的位置
keys[parent] = value;
print(keys);
}
// 堆排序(降序),最小堆
public static void heapSort(int[] keys) {
heapSort(keys, true);
}
// 堆排序,当minheap为true时,创建最小堆,降序排序;否则创建最大堆,升序排序
public static void heapSort(int[] keys, boolean minheap) {
// 创建最小/大堆,根结点值最小/大
for (int i = keys.length / 2 - 1; i >= 0; i--) {
sift(keys, i, keys.length - 1, minheap);
}
// 每趟将最小/大值交换到后面,再调整成最小/大堆
for (int i = keys.length - 1; i > 0; i--) {
// 交换keys[0]与keys[i]
swap(keys, 0, i);
sift(keys, 0, i - 1, minheap);
}
}
public static void main(String[] args){
int[] values=HeapSort.randomInt(10, 100);
System.out.print("关键字序列:");
HeapSort.print(values);
HeapSort.heapSort(values);
}
}
输出如下:
关键字序列:64 57 29 75 8 53 98 78 78 53
sift 4..9 64 57 29 75 8 53 98 78 78 53
sift 3..9 64 57 29 75 8 53 98 78 78 53
sift 2..9 64 57 29 75 8 53 98 78 78 53
sift 1..9 64 8 29 75 53 53 98 78 78 57
sift 0..9 8 53 29 75 57 53 98 78 78 64
sift 0..8 29 53 53 75 57 64 98 78 78 8
sift 0..7 53 57 53 75 78 64 98 78 29 8
sift 0..6 53 57 64 75 78 78 98 53 29 8
sift 0..5 57 75 64 98 78 78 53 53 29 8
sift 0..4 64 75 78 98 78 57 53 53 29 8
sift 0..3 75 78 78 98 64 57 53 53 29 8
sift 0..2 78 98 78 75 64 57 53 53 29 8
sift 0..1 78 98 78 75 64 57 53 53 29 8
sift 0..0 98 78 78 75 64 57 53 53 29 8