算法基础 -- 小根堆构建的两种方式:上浮法与下沉法

小根堆构建的两种方式:上浮法与下沉法

在构建小根堆(Min-Heap)时,通常有两种常见的构建方式:

  1. 上浮建堆(逐个插入,上浮调整)
  2. 下沉建堆(Heapify 自底向上,下沉调整)

这两种方法在时间复杂度上有显著差异。


一、上浮建小根堆:逐个插入 + 上浮调整

1. 核心原理:

  • 对于给定的无序数组,逐个插入到堆中。

  • 每次插入新元素时,将其放在堆的最后一个位置(末尾),然后执行"上浮"调整:

    • 将新元素与其父节点比较,如果新元素更小,则与父节点交换。
    • 重复此过程,直到新元素达到正确的位置或成为堆顶。

2. 上浮过程示例:

  • 对于每个新插入的元素,最多需要调整至堆顶。
  • 在完全二叉树中,高度为 ⌊ log ⁡ n ⌋ \lfloor \log n \rfloor ⌊logn⌋。
  • 因此,单个元素上浮的时间复杂度为 O ( log ⁡ n ) O(\log n) O(logn)。

3. 总体时间复杂度分析:

  • 对于 n n n 个元素,逐个插入,每次上浮调整:

    O ( 1 × log ⁡ 1 ) + O ( 1 × log ⁡ 2 ) + ⋯ + O ( 1 × log ⁡ n ) O(1 \times \log 1) + O(1 \times \log 2) + \cdots + O(1 \times \log n) O(1×log1)+O(1×log2)+⋯+O(1×logn)

  • 这相当于一个对数级数求和:

    ∑ i = 1 n log ⁡ i ≈ O ( n log ⁡ n ) \sum_{i=1}^{n} \log i \approx O(n \log n) i=1∑nlogi≈O(nlogn)

  • 结论:上浮建堆的时间复杂度为 O ( n log ⁡ n ) O(n \log n) O(nlogn)


二、下沉建小根堆:Heapify 自底向上

1. 核心原理:

  • 直接将无序数组视为一个完全二叉树。

  • 从最后一个非叶子节点开始,逐个向前进行"下沉"调整:

    • 对当前节点执行下沉:

      • 与左右子节点中较小的一个交换,确保当前节点保持小根堆性质。
    • 重复下沉,直到当前节点满足堆性质或成为叶节点。

2. 下沉过程示例:

  • 对于每个非叶子节点进行下沉操作。

  • 下沉操作的时间取决于树的高度:

    • 对于完全二叉树,树高为 ⌊ log ⁡ n ⌋ \lfloor \log n \rfloor ⌊logn⌋。

    • 但下沉的层次是逐级减少的:

      • n / 2 n/2 n/2 个节点(叶节点)不需要下沉。
      • n / 4 n/4 n/4 个节点下沉 1 次。
      • n / 8 n/8 n/8 个节点下沉 2 次。
      • ......

3. 总体时间复杂度分析:

  • 这是一种渐进减半的过程

    ∑ i = 1 log ⁡ n n 2 i × i \sum_{i=1}^{\log n} \frac{n}{2^i} \times i i=1∑logn2in×i

  • 该求和公式的复杂度为 O ( n ) O(n) O(n),这是因为下沉过程中的递减效果:

T ( n ) = 2 × n 2 × 1 + 2 × n 4 × 2 + 2 × n 8 × 3 + ⋯ ≈ O ( n ) T(n) = 2 \times \frac{n}{2} \times 1 + 2 \times \frac{n}{4} \times 2 + 2 \times \frac{n}{8} \times 3 + \cdots \approx O(n) T(n)=2×2n×1+2×4n×2+2×8n×3+⋯≈O(n)

  • 结论:下沉建堆的时间复杂度为 O ( n ) O(n) O(n)

三、两种建堆方式的时间复杂度对比

建堆方式 上浮建堆(逐个插入) 下沉建堆(Heapify)
原理 逐个插入,上浮调整 自底向上,下沉调整
调整过程 每次上浮至正确位置 从最后一个非叶节点下沉
复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn) O ( n ) O(n) O(n)

四、为什么下沉建堆更高效?

  • 下沉建堆(Heapify)直接从中间节点开始调整,避免了对叶子节点的重复操作。
  • 叶子节点天生满足堆的性质,因此可以忽略。
  • 而上浮建堆在每次插入时都进行上浮,无法利用已经部分有序的特性,导致较高的复杂度。

五、实际应用中的选择:

  • 上浮建堆: 常用于动态增量插入堆的情况(如优先队列逐个入队)。
  • 下沉建堆: 常用于一次性构建堆(如堆排序)。
相关推荐
无小道3 小时前
算法——暴力+优化
算法·优化·暴力
Free Tester3 小时前
如何判断 LeakCanary 报告的严重程度
java·jvm·算法
zyq99101_14 小时前
DFS算法实战:经典例题代码解析
python·算法·蓝桥杯·深度优先
智者知已应修善业4 小时前
【51单片机单按键切换广告屏】2023-5-17
c++·经验分享·笔记·算法·51单片机
广州灵眸科技有限公司4 小时前
为RK3588注入澎湃算力:RK1820 AI加速卡完整适配与评测指南
linux·网络·人工智能·物联网·算法
qinian_ztc4 小时前
frida 14.2.18 安装报错解决
算法·leetcode·职场和发展
AI应用实战 | RE4 小时前
012、检索器(Retrievers)核心:从向量库中智能查找信息
人工智能·算法·机器学习·langchain
凤年徐4 小时前
C++手撕红黑树:从0到200行,拿下STL map底层核心
c++·后端·算法
Thomas.Sir4 小时前
AI 医疗之罕见病/疑难病辅助诊断系统从算法到实现【表型驱动与知识图谱推理】
人工智能·算法·ai·知识图谱
tankeven5 小时前
动态规划专题(03):区间动态规划从原理到实践(未完待续)
c++·算法·动态规划