实现步骤
- 把数组用堆的形式排列(小堆或者大堆)
- 对堆进行排序
Step1. 建堆
方法一:把第一个数就看成是一个堆,之后的数据依次当作push数据,再向上调整堆到合适位置。
- 如图,第一个数是70,已经是一个堆
 - 插入56,进行向上调整(此处认为建小堆)

- 插入30,再次调整堆,依次类推…

方法二:使用向下调整算法。
向下调整算法的前提左右子树都是堆。
Q: 这里有一个问题?该从哪里开始调整。
因为叶子节点没有左右子树,叶子所在的子树不需要调整,所以要从倒数第一个非叶子节点的子树开始,即:最后一个结点的父亲。

Step2. 排序建堆
结论: 排升序,选大堆;排降序,选小堆。
如果排升序,选择小堆 每一次选走了堆顶元素,剩下的数字就会失去堆的结构,需要重新建堆。选择小堆不是不可以,但是时间复杂度是N*N,排序效率太低了。

如果排大堆
建大堆,可以选出最大的数;最大的数(堆顶)和最后一个数交换,相当于pop了堆顶后再次进行向下调整。向下调整算法的时间复杂度n个数 : N*logN

堆排序代码(排升序)
void HeapSort(int* a, int n)
{
for (int i = (n - 1 - 1) / 2; i >= 0; --i)
{
AdjustDown(a, n, i);
}
for (int end = n - 1; end > 0; --end)
{
Swap(&a[end], &a[0]);
AdjustDown(a, end, 0);
}
}
|