一、定义
借助堆结构实现的排序算法被称为堆排序。
二、过程说明
1、建堆
(1)方法1
原地建堆,对于数组来说,从前往后;对于树来说,从下向上。
将数组的第一个元素作为堆顶,第二个元素做向堆中插入数据的操作,即:从下向上堆化。直至所有的元素均完成所有插入操作,此时堆就建立完成了。
(2)方法2
原地建堆,对于数组来说,从后往前;对于树来说,从上向下。
从数组倒数第一个非叶子节点向下进行堆化,之后是倒数第二个非叶子节点向下堆化,直至堆化到数组第一个节点,从而完成堆的建立。
(3)方法 2 和方法 1 的区别
方法 2 默认数组开始时已经是一颗树了,但是不是堆结构。之后的操作就是不断比较交换,使得该树满足堆结构。
方法 1 则从 0 开始建堆,当树建好时,就是一颗标准的堆了。
(4)时间复杂度
这里说下方法 2 的时间复杂度。实际上真正进行堆化的节点为非叶子节点,并且是从上到下进行堆化。每个节点堆化的时间复杂度实际上是该节点的高度,总结如下图所示:
经过下图推算,得出时间复杂度为 O(n) 。
2、排序
堆建完之后排序就很简单了,因为此时的堆顶已经是最大值(最小值)了,取出该值放到叶子节点的位置,原本叶子节点位置的数值移动到堆顶点,在进行一次从上到下的堆化,重新得到堆顶是第 2 大(小)的数。经过多次堆化,就能得到从大到小或者从小到大的数据了。
排序阶段的时间复杂度为 O(nlogn),因为每次堆化时都是将叶子节点放到顶点然后从上到下堆化,堆化一次就相当于比较 logn 次,logn 为树的高度,需要比较 n 次,所以时间复杂度为 O(nlogn) 。
由于建堆 + 排序的时间复杂度为 O(n) + O(nlogn),省略之后时间复杂度为 O(nlogn) 。
三、总结
由于堆排序的过程中,需要轮着将数据放到堆顶点进行堆化,导致该排序不是稳定性排序。
同时由于整个过程只需要在本数组内就能完成整个过程,需要其他内存很少,故堆排序时原地排序。
| 算法种类 | 时间复杂度 | 空间复杂度 | 原地排序 | 稳定性排序 |
| 堆排序 | O(nlogn) | O(n) | √ | × |
参考:极客时间《数据结构与算法之美》王争
这门课真心推荐,内容很经典、栗子很形象,里面还包含了很多面试题目。真是居家旅行必备良药。
(SAW:Game Over!)