数据结构与算法演示台SUANFA.NET.CN · STEP BY STEP

排序 · 单步演示

堆排序

把数组看成一棵完全二叉树,先整理成大顶堆(每个结点都不小于孩子),堆顶就是最大值;把它换到末尾,堆缩小一格,再让新的堆顶往下沉,重复到堆里只剩一个数。

1 到 16 个整数(−99 到 999),用逗号或空格隔开。 输入只在你的浏览器里计算,不会上传。

380
121
712
53
444
265
906
177

当前操作已就位

步 001 / 084初始数组。把数组看成一棵完全二叉树:a[i] 的孩子是 a[2i+1] 和 a[2i+2]。先建大顶堆,再反复把堆顶换到末尾。

键盘: 单步,空格 播放/暂停(先点一下演示区)。

伪代码 · 当前行高亮

  1. for i ← ⌊n/2⌋−1 down to 0:下沉(i, n)
  2. for end ← n−1 down to 1
  3. 交换 a[0]、a[end]
  4. 下沉(0, end)
  5. 下沉(i, size):
  6. largest ← i;l ← 2i+1;r ← 2i+2
  7. if l < size 且 a[l] > a[largest]:largest ← l
  8. if r < size 且 a[r] > a[largest]:largest ← r
  9. if largest ≠ i:交换 a[i]、a[largest];i ← largest;回到上一步

变量

比较次数0
交换/写入次数0

复杂度

最好情况O(n log n)
平均情况O(n log n)
最坏情况O(n log n)
额外空间O(1)
稳定性不稳定

自底向上建堆总共是 O(n);之后 n−1 次取堆顶,每次下沉最多走树高 log₂n 层。全程在原数组里做,不需要额外空间。

要点

  • 下标关系:a[i] 的孩子是 a[2i+1]、a[2i+2],父亲是 a[⌊(i−1)/2⌋]。
  • 建堆从最后一个有孩子的结点 ⌊n/2⌋−1 开始往前做,叶子不用处理。
  • 最坏情况也是 O(n log n),且不需要额外数组。

常见错误

下沉时只和左孩子比、忘了右孩子,堆性质就会被破坏,排出来的结果会错。

同一类的其他演示