讲师中心 微信公众号

工具推荐

视频效率加速
立刻MV
立刻MV

低成本歌曲 MV、视频生成

updream

一键生成高质量推广成片

Laper
Laper

剧本策划到成片协作

AniShort
AniShort

AI短剧协同制作平台

c++怎么实现二叉堆的向上调整与向下调整_c++ 优先队列底层逻辑【详解】

夜芳酱_6224

夜芳酱_6224

发布时间:2026-01-03 10:33:33

|

819人浏览过

|

来源于php中文网

原创

向上调整需确保i>0再算父节点索引,用有符号int防绕回;向下调整须先判left

c++怎么实现二叉堆的向上调整与向下调整_c++ 优先队列底层逻辑【详解】

向上调整 heapify_up 怎么写才不越界

向上调整发生在插入新元素后,把新节点从堆底一路“浮”到合适位置。关键不是“怎么比较”,而是**索引计算必须防越界**——父节点索引是 (i - 1) / 2,但当 i == 0(已在根)时必须立即停止。

常见错误是写成 while (i > 0 && arr[i] > arr[(i-1)/2]) 却忘了在循环体内更新 i 后没检查新 i 是否仍合法;更隐蔽的坑是用无符号整数(如 size_t i),i - 1 会绕回极大值,直接崩。

  • 始终用有符号整型(如 int)作下标变量
  • 循环条件严格写成 i > 0,且更新 i 后不依赖后续判断来兜底
  • 比较前不假设父节点存在——i > 0 就是唯一安全前提
void heapify_up(vector<int>& heap, int i) {
    while (i > 0) {
        int parent = (i - 1) / 2;
        if (heap[i] <= heap[parent]) break; // 小顶堆:子不小于父则停
        swap(heap[i], heap[parent]);
        i = parent;
    }
}

向下调整 heapify_down 的三个子节点边界判断

向下调整用于弹出堆顶或修改根后,把顶部元素“沉”到底部。难点不在逻辑,而在**左右子节点索引是否越界**:左子为 2*i + 1,右子为 2*i + 2,但这两个索引随时可能 ≥ heap.size()。

不能只写 if (left heap[largest]) 就完事——如果 left 已越界,right 就不该参与比较;更糟的是,有些实现先算 right 再判断,导致 right 计算本身越界(尤其用无符号类型)。

立即学习“C++免费学习笔记(深入)”;

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 先算 left = 2*i + 1,若 left >= size,直接退出(无子节点)
  • 再算 right = left + 1,仅当 right 才和 <code>left 比较选大者
  • 选中的最大子节点必须和当前节点比较,且 swap 后要继续向下,不能漏掉深层调整
void heapify_down(vector<int>& heap, int i, int size) {
    while (true) {
        int largest = i;
        int left = 2 * i + 1;
        if (left < size && heap[left] > heap[largest]) largest = left;
        int right = left + 1;
        if (right < size && heap[right] > heap[largest]) largest = right;
        if (largest == i) break;
        swap(heap[i], heap[largest]);
        i = largest;
    }
}

std::priority_queue 底层真用 vector + 手动调整吗

是的,std::priority_queue 默认容器是 std::vector,默认比较器是 std::less(大顶堆),所有插入、弹出都靠隐式调用 push_heap / pop_heap,而这两个函数底层就是你写的 heapify_up 和 heapify_down 的泛型版本。

但它不直接暴露调整函数——你无法对已有 vector 调用 make_heap 后再手动调用 push_heap,除非你用原始数组或迭代器区间。实际项目中,如果需要中途修改某个元素并重平衡,priority_queue 无能为力,必须自己维护 vector + 下标映射 + 手动调整。

  • priority_queue 的 top() 是 O(1),push() 和 pop() 都是 O(log n)
  • 它不提供“降低/升高某元素优先级”的接口,这是很多算法(如 Dijkstra)必须手写堆的原因
  • 调试时可把内部 c 成员(底层容器)用 const_cast 强转出来观察,但别修改——破坏堆序会导致后续操作未定义行为

小顶堆 vs 大顶堆:改一个参数还是重写两套逻辑

别重写。C++ 标准库靠比较器控制堆序:priority_queue<int vector>, greater<int>></int></int> 是小顶堆,less<int></int> 是大顶堆。自己实现时也应统一用模板比较器,而不是硬编码 > 或 。

真正容易错的是:以为把所有 > 换成 就行——其实向上/向下调整中“违反堆序”的判定方向必须一致。例如小顶堆要求父 ≤ 子,那么 <code>heapify_up 中就要写 if (heap[i] >= heap[parent]) break;,不是简单翻转符号。

  • 把比较逻辑抽成独立函数对象或 lambda,传入调整函数
  • 测试时务必用混杂正负数的用例,避免因全正/全负掩盖符号错误
  • 注意 std::greater 对自定义类型需重载 operator>,而 std::less 需 operator,别搞反

真实场景里,最常被忽略的是调整过程中对容器 size 的动态信任——比如在 heapify_down 里传入的 size 如果不是当前有效长度(例如删了元素但没 shrink),就会访问野指针;或者多线程环境下没加锁,size() 和后续下标访问之间被 resize 了。这些不会报编译错误,但 core dump 很安静。

热门AI工具

更多
二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

函子Zion

一款支持AI搭建、可视化编辑和多端发布的全栈无代码开发平台。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

超级麦吉

一款通过数字员工协作完成调研、数据分析与文档制作的AI办公平台。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

码上飞
码上飞 Hot

一款基于自然语言的AI应用开发平台,可根据用户描述自动生成应用程序,帮助个人和团队快速完成应用原型与开发。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
Sass和less的区别
Sass和less的区别

Sass和less的区别有语法差异、变量和混合器的定义方式、导入方式、运算符的支持、扩展性等。本专题为大家提供Sass和less相关的文章、下载、课程内容,供大家免费下载体验。

3327

2023.10.12

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

354

2023.09.25

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

3340

2025.10.15

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

867

2025.10.24

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

7539

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3565

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

4708

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

3145

2025.08.29

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

40

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
LLVM Programmer’s Manual
LLVM Programmer’s Manual

共0课时 | 0人学习

Conan 包创建教程
Conan 包创建教程

共0课时 | 0人学习

Visual Studio 入门指南
Visual Studio 入门指南

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn