堆排序可以认为是对选择排序的优化,可以用二叉堆来实现,具体流程如下:
- 对序列原地建堆(heapify)
- 重复执行以下操作,指导堆元素的数量为1
- 交换堆顶和堆尾元素
- 堆的元素减1
- 对堆顶元素进行一次下滤
/**
* 堆排序
*
* @author zhangj
* @date 2020/9/23
*/
public class HeapSort {
private int[] elements;
private int size;
/**
* 构造函数
*
* @param elements
*/
public HeapSort(int[] elements) {
this.elements = elements;
}
/**
* 排序
*/
private void sort() {
size = elements.length;
//原地建堆
for (int i = ((size >> 1) - 1); i >= 0; i--) {
siftDown(i);
}
while (size > 1) {
//交换堆头和堆尾元素
int tmp = elements[0];
elements[0] = elements[size - 1];
elements[size - 1] = tmp;
//数量减一
size--;
//堆头元素下滤
siftDown(0);
}
}
/**
* 下滤操作
*
* @param index
*/
private void siftDown(int index) {
int value = elements[index];
int half = size >> 1;
while (index < half) {
int leftIndex = (index << 1) + 1;
int leftValue = elements[leftIndex];
int rightIndex = leftIndex + 1;
if (rightIndex < size) {
int rightValue = elements[rightIndex];
if (rightValue > leftValue) {
leftIndex = rightIndex;
leftValue = rightValue;
}
}
if (value > leftValue) {
break;
}
elements[index] = leftValue;
index = leftIndex;
}
elements[index] = value;
}
}
总结: 堆排序时间复杂度为O(nlogn),空间复杂度为O(1)