阅读本文需先知晓堆的定义与堆排序的实现
堆排序的步骤分两步
- 首先把序列变成一个有序堆
- 再不断交换堆顶的最大元素和堆底元素,每次交换都像是选择排序般取走了剩余序列中的最大值
所以我们可以分两个步骤计算堆排序的时间复杂度
有序堆的构造:等价于对非叶子节点从下至上的下沉操作
- 假设堆高h为一整数,堆有n个节点,那么h = log2n
- 该堆有2h个叶子节点,由于叶子节点是最底层,所以无需下沉
- 倒数第二层的节点有2h-1个,该层节点下沉到叶子节点至多需要比较2次(兄弟节点的比较,父节点与较大的兄弟节点的比较),交换1次(如果父节点小于子节点则交换)
- 倒数第三层有2h-2个非叶子节点,他们下沉到倒数第二层之后还要继续下沉到叶子节点(倒数第三层的节点可能比叶子节点还小,所以还要下沉到叶子节点),所以对倒数第二层的节点其下沉至多需要比较4次,交换2次。
- 以此类推,倒数第n层的下沉所需操作数 = 该层节点数 * 该层节点下沉所需的操作数 ,前者为2h-n+1,后者为3(n-1)。
- 所以根节点作为倒数第h+1层,它的下沉所需操作数就为2h-(h+1)+1 * 3 (h+1-1) = 20 * 3h。
- 将各层的下沉所需操作数从上至下相加,就是构造整个有序堆的所需操作数:3 ( 20h + 21(h-1) + 22(h-2) +…2h-1 ),设该式为a,则2a - a = 3 ( 21 + 22 +…2h - h ),根据等比序列的求和公式,我们可以知道a = 3 ( 2h+1 - 2 - h),代入h,得a = 3(2n - 2 - log2n) ≈ 6n。
- 综上,建有序堆的时间复杂度是O(n)。
不断交换堆顶元素和堆底元素
- 共进行n-1次交换,所需操作数为n-1
- 并且每次交换都会导致根节点不再是堆中的最大元素,所以需要对新的根节点进行下沉操作,所需操作数为3(n-1)h,即3(n-1)log2n
- 综上,该过程所需操作数为n-1 + 3(n-1)log2n = (n-1)(3log2n + 1),时间复杂度即为O(nlogn)