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

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

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

五、实际应用中的选择:

  • 上浮建堆: 常用于动态增量插入堆的情况(如优先队列逐个入队)。
  • 下沉建堆: 常用于一次性构建堆(如堆排序)。
相关推荐
Aaron158818 小时前
基于VU13P在人工智能高速接口传输上的应用浅析
人工智能·算法·fpga开发·硬件架构·信息与通信·信号处理·基带工程
予枫的编程笔记18 小时前
【论文解读】DLF:以语言为核心的多模态情感分析新范式 (AAAI 2025)
人工智能·python·算法·机器学习
im_AMBER18 小时前
Leetcode 99 删除排序链表中的重复元素 | 合并两个链表
数据结构·笔记·学习·算法·leetcode·链表
王老师青少年编程18 小时前
信奥赛C++提高组csp-s之欧拉回路
c++·算法·csp·欧拉回路·信奥赛·csp-s·提高组
墨有66618 小时前
数学分析栈的出栈顺序:从算法判断到数学本质(卡特兰数初探)
c++·算法·数学建模
zhutoutoutousan18 小时前
氛围数学学习:用游戏化思维征服抽象数学
学习·算法·游戏
guygg8819 小时前
基于捷联惯导与多普勒计程仪组合导航的MATLAB算法实现
开发语言·算法·matlab
fengfuyao98519 小时前
遗传算法与粒子群算法求解非线性函数最大值问题
算法
LeetCode天天刷19 小时前
【软件认证】比特翻转【滑动窗口】
算法
源代码•宸19 小时前
Leetcode—1123. 最深叶节点的最近公共祖先【中等】
经验分享·算法·leetcode·职场和发展·golang·dfs