【数据结构】堆排序的算法复杂度分析

说明:阅读本文章的前提是对堆排序过程有大致了解,此处重点讲解算法的复杂度

堆排序的过程

Created with Raphaël 2.2.0 开始 建立初始堆 待排序元素个数大于1? 交换堆顶元素和堆底元素 将剩余待排序元素重新建立堆 结束 yes no

每次交换堆顶元素和堆底元素之后,待排序元素个数就少一个


初始状态
初始状态

建立初始堆(大根堆)

依次从后往前逐渐调整,只考虑非叶子节点(分支节点),第一个调整的元素为“最后一个非叶子节点”,即【233】

  1. 考虑【233】

其左孩子为【888】,无右孩子。【888】比【233】大,交换【233】与【888】。结果如下:
在这里插入图片描述
交换后,【233】无孩子节点,无需继续考虑【233】

  1. 考虑【666】

其左右孩子中,【985】比【688】大。且【985】比【666】也大,交换【666】与【985】。结果如下:
在这里插入图片描述
交换后,【666】无孩子节点,无需继续考虑【666】

  1. 考虑【211】

其左右孩子中,【985】比【888】大。且【985】比【211】也大,交换【211】与【985】。结果如下:
在这里插入图片描述
交换后,【211】有孩子节点。其左右孩子中,【688】比【666】大。且【688】比【211】也大,交换【211】与【688】。结果如下:
在这里插入图片描述
至此,已建立大根堆


交换堆顶元素与堆底元素,并重新调整大根堆

  • 将堆顶元素【985】与堆底元素【233】交换。结果如下:
    在这里插入图片描述

此时待排序元素(前5个)已不是大根堆,需要重新调整为大根堆

考虑堆顶元素【233】
其右孩子【888】比左孩子【688】更大。且【888】比【233】也大。交换【233】与【888】。结果如下:
在这里插入图片描述
交换后,【233】无孩子节点(985为排好序的元素),无需继续考虑【233】

  • 将堆顶元素【888】与堆底元素【666】交换。结果如下:
    在这里插入图片描述

此时待排序元素(前4个)已不是大根堆,需要重新调整为大根堆

考虑堆顶元素【666】
其左孩子【688】比左孩子【233】更大。且【688】比【666】也大。交换【666】与【688】。结果如下:
在这里插入图片描述
交换后,【666】有左孩子节点【211】(888为排好序的元素),但【211】比【666】小,不再进行调整

  • 将堆顶元素【688】与堆底元素【211】交换。结果如下:
    在这里插入图片描述

此时待排序元素(前3个)已不是大根堆,需要重新调整为大根堆

考虑堆顶元素【211】
其左孩子【666】比左孩子【233】更大。且【666】比【211】也大。交换【211】与【666】。结果如下:
在这里插入图片描述
交换后,【211】无孩子节点(688、888为排好序的元素),无需继续考虑【211】

  • 将堆顶元素【666】与堆底元素【233】交换。结果如下:
    在这里插入图片描述

此时待排序元素(前2个)仍是大根堆,无需调整

  • 将堆顶元素【233】与堆底元素【211】交换。结果如下:
    在这里插入图片描述

此时待排序元素(前1个)仍是大根堆,无需调整。

排序完成(升序),211<233<666<688<888<985

时间复杂度

建堆的时间复杂度

在调整堆时,每交换一次节点,最多比较关键字2次

  • 比较1次:目标节点只有左孩子,无右孩子,将目标节点与其左孩子比较1下
  • 比较2次:目标节点左右孩子均有,首先左右孩子先比较1下,然后大者再与目标节点比较1下

若目标节点在 x x x层,树高为 h h h,则调整时,目标节点最多交换 ( h − x ) (h-x) (hx)次,每次最多比较2次关键字,故 x x x层节点的关键字对比次数不超过 2 × ( h − x ) 2\times(h-x) 2×(hx)

假设一颗完全二叉树,树高为h,最后一层节点无需进行调整
第1层共有1个节点,关键字对比次数最多为 1 × 2 × ( h − 1 ) 1\times2\times(h-1) 1×2×(h1)
第2层共有2个节点,关键字对比次数最多为 2 × 2 × ( h − 2 ) 2\times2\times(h-2) 2×2×(h2)
第h-1层共有2h-2个节点,关键字对比次数最多 2 h − 2 × 2 × 1 2^{h-2}\times2\times1 2h2×2×1
将整颗树调整为大根堆,关键字对比次数最多 1 × 2 × ( h − 1 ) + 2 × 2 × ( h − 2 ) + . . . + 2 h − 2 × 2 × 1 1\times2\times(h-1)+2\times2\times(h-2)+...+2^{h-2}\times2\times1 1×2×(h1)+2×2×(h2)+...+2h2×2×1

处理上式为: ∑ i = 1 h − 1 2 i − 1 × 2 × ( h − i ) = ∑ i = 1 h − 1 2 i × ( h − i ) \sum_{i=1}^{h-1}2^{i-1}\times2\times(h-i)=\sum_{i=1}^{h-1}2^{i}\times(h-i) i=1h12i1×2×(hi)=i=1h12i×(hi)
由于n个节点的完全二叉树的高 h = log ⁡ 2 n + 1 h=\log_2 n+1 h=log2n+1(向下取整)
令 j = h − i , 则 i = h − j 。 令j=h-i,则i=h-j。 j=hii=hj原式 = ∑ j = h − 1 1 2 h − j × j = ∑ j = log ⁡ 2 n 1 2 log ⁡ 2 n + 1 − j × j = ∑ j = log ⁡ 2 n 1 n × 2 × 2 − j × j = 2 n × ∑ j = log ⁡ 2 n 1 2 − j × j =\sum_{j=h-1}^{1} 2^{h-j} \times j=\sum_{j=\log_2 n}^{1} 2^{\log_2 n +1-j} \times j=\sum_{j=\log_2 n}^{1} n\times 2 \times 2^{-j} \times j=2n\times \sum_{j=\log_2 n}^{1} 2^{-j} \times j =j=h112hj×j=j=log2n12log2n+1j×j=j=log2n1n×2×2j×j=2n×j=log2n12j×j

考虑 S n = ∑ j = h 1 2 − j × j = ∑ j = 1 h 2 − j × j = 1 × 1 2 + 2 × 1 4 + 3 × 1 8 + . . . + h × 1 2 h S_n=\sum_{j=h}^{1} 2^{-j} \times j=\sum_{j=1}^{h} 2^{-j} \times j=1\times\frac{1}{2}+2\times\frac{1}{4}+3\times\frac{1}{8}+...+h\times\frac{1}{2^h} Sn=j=h12j×j=j=1h2j×j=1×21+2×41+3×81+...+h×2h1
① × 1 2 ①\times\frac{1}{2} ×21 1 2 S n = 1 × 1 4 + 2 × 1 8 + . . . + ( h − 1 ) × 1 2 h + h × 1 2 h + 1 \frac{1}{2}S_n=1\times\frac{1}{4}+2\times\frac{1}{8}+...+(h-1)\times\frac{1}{2^h}+h\times\frac{1}{2^{h+1}} 21Sn=1×41+2×81+...+(h1)×2h1+h×2h+11
使用错误相减法②-①得: 1 2 S n = 1 2 + 1 4 + 1 8 + . . . + 1 2 h − h × 1 2 h + 1 = 1 2 ( 1 − 1 2 n ) 1 − 1 2 − h × 1 2 h + 1 = 1 − 1 2 n − h 2 h + 1 \frac{1}{2}S_n=\frac{1}{2}+\frac{1}{4}+\frac{1}{8}+...+\frac{1}{2^{h}}-h\times\frac{1}{2^{h+1}}=\frac{\frac{1}{2}(1-\frac{1}{2^n})}{1-\frac{1}{2}}-h\times\frac{1}{2^{h+1}}=1-\frac{1}{2^n}-\frac{h}{2^{h+1}} 21Sn=21+41+81+...+2h1h×2h+11=12121(12n1)h×2h+11=12n12h+1h
③ × 2 ③\times2 ×2得: S n = 2 − 1 2 h − 1 − h 2 h S_n=2-\frac{1}{2^{h-1}}-\frac{h}{2^h} Sn=22h112hh
很明显④式小于2即 S n < 2 , 所 以 2 n × ∑ j = log ⁡ 2 n 1 2 − j × j < 4 n S_n< 2,所以2n\times \sum_{j=\log_2 n}^{1} 2^{-j} \times j<4n Sn<22n×j=log2n12j×j<4n

建堆的时间复杂度为O(n)

交换堆顶底元素后重建堆的时间复杂度

每次将堆顶元素与堆底元素进行交换后,需要将剩余待排序元素重新建堆。此时处理的是堆顶元素,即根节点。根节点位于第一层,关键字最多比较次数为 2 × ( h − 1 ) 2\times(h-1) 2×(h1)次。
上述过程共需进行n-1次(n为节点个数),故重建堆的总的关键字最多比较次数为 2 × ( h − 1 ) × ( n − 1 ) = 2 log ⁡ 2 n ( n − 1 ) 2\times(h-1)\times(n-1)=2\log_2 n (n-1) 2×(h1)×(n1)=2log2n(n1)

重建堆的时间复杂度为O(nlogn)

堆排序的时间复杂度为O(nlogn)+O(n)=O(nlogn)

空间复杂度

整个排序过程,包括初建堆、交换顶底元素、重建堆,未用到其他多余的空间,主要进行比较与交换工作,所以空间复杂度是O(1)

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序鸡

如果帮到您,点个赞鼓励一下吧。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值