Version: Next

堆排序

  • 对排序可以认为是对选择排序的优化

执行流程

  1. 对序列进行原地建堆 (Heapify)
  2. 重复执行以下操作,直到堆的元素数量 size1
    1. 交换堆顶元素和尾元素 (即交换当前堆中的最大值和最小值)
    2. 堆的元素数量 -1size -= 1
    3. 0 位置进行 1 次 siftDown 操作,让它排列到堆中的合适位置

复杂度分析

  • 生成 n 次堆,O(n)
  • 对每一个堆
    • 交换元素 O(1)
    • size - 1 , O(1)
    • siftDown,需要进行二分搜索,O(logn)
  • 最终 O(nlogn)
/**
* 对排序
*/
public class HeapSort<E extends Comparable<E>> extends Sort<E> {
private int heapSize;
public HeapSort(E[] array) {
this.array = array;
}
@Override
public void sort() {
// 原地建堆
heapSize = array.length;
for (int i = (heapSize >> 1) - 1; i >= 0; i--) {
siftDown(i);
}
while (heapSize > 1) {
swap(0, heapSize - 1); // 交换头尾
heapSize--;
// 对 0 位置进行 siftDown()
siftDown(0); // 排列,位置堆的性质
}
}
private void siftDown(int index) {
E element = this.array[index];
int half = heapSize >> 1;
while (index < half) { // index 必须是非叶子节点
// 默认是左边根父节点比
int childIndex = (index << 1) + 1;
E child = this.array[childIndex];
int rightIndex = childIndex + 1;
// 右子节点比左子节点大
if (rightIndex < heapSize && cmp(this.array[rightIndex], child) > 0)
child = this.array[childIndex = rightIndex];
// 大于等于子节点
if (cmp(element, child) >= 0) break;
this.array[index] = child;
index = childIndex;
}
this.array[index] = element;
}
public static void main(String[] args) {
Integer[] array = {4, 5, 2, 3, 1};
HeapSort<Integer> integerHeapSort = new HeapSort<>(array);
integerHeapSort.sort();
for (Integer integer : array) {
System.out.println(integer + " ");
}
}
}