C++ 怎么实现堆排序 C++ make_heap与sort_heap使用【STL】

发布时间 - 2026-01-29 00:00:00    点击率:
make_heap仅构建堆结构而不排序,需配合sort_heap才能完成排序;它时间复杂度O(n),但要求输入为随机访问迭代器,且必须与sort_heap使用相同比较函数。

make_heap 为什么不能直接当排序用

make_heap 只把容器转成最大堆(或最小堆),不保证元素有序。它只调整结构满足堆性质:每个节点值 ≥(或 ≤)其子节点,但根最大、叶子最小,并不等于“从大到小排列”。常见误用是调完 make_heap 就以为排好了,结果一打印发现顺序乱的。

典型场景:你有一段 vector v = {3,1,4,1,5};,执行 make_heap(v.begin(), v.end()); 后,v 可能变成 {5,3,4,1,1} —— 满足堆序,但不是升序/降序。

  • 默认构造最大堆(less),想最小堆得显式传 greater()
  • 时间复杂度 O(n),但只是建堆,不是排序
  • 底层依赖随机访问迭代器,list 不能用

sort_heap 必须在 make_heap 之后调用

sort_heap 的前提条件很硬:它要求输入区间**已经是合法堆**。如果直接对普通数组调 sort_heap,行为未定义,大概率崩溃或输出垃圾数据。错误现象包括:程序闪退、部分元素重复、最后几个数完全错位。

正确链条只有这一种:make_heap → (可选 push_heap/pop_heap)→ sort_heap。其中 sort_heap 是个“一次性操作”:它把堆逐个弹出最大元放到末尾,最终得到升序序列(对最大堆而言)。

  • 对最大堆调 sort_heap 得升序;若要降序,先用 greater() 建最小堆,再调 sort_heap
  • 调用后原堆结构被破坏,不能再当堆用
  • 必须和 make_heap 用同一比较函数,否则结果不可预测

完整堆排序三步写法(含自定义比较)

标准堆排序流程就是三行 STL 调用,但每行参数必须对齐。例如按绝对值升序排:

vector v = {-3, 2, -1, 4};
auto abs_less = [](int a, int b) { return 

abs(a) < abs(b); }; make_heap(v.begin(), v.end(), abs_less); sort_heap(v.begin(), v.end(), abs_less); // v 现在是 {-1, 2, -3, 4}(abs: 1,2,3,4)

注意点:

  • lambda 捕获为空时才能作为模板参数,所以不能带 [&][=]
  • 如果用函数对象(如 struct AbsLess { bool operator()(...) {...} };),要确保 operator() 是 const
  • sort_heap 不接受 std::execution::par 等策略,纯串行

性能与边界提醒:别在 vector 外反复调 heap 函数

STL 堆函数都假设容器内存连续且迭代器有效。vector 中间 eraseinsert 后,原有堆结构全失效,必须重调 make_heap,不能靠 push_heap 补救——因为 push_heap 只处理“最后一个元素插入后”的情况,前提是前面仍是堆。

另一个易忽略点:make_heapsort_heap 对空区间或单元素区间安全,但传入 v.end()v.end() 这种无效范围会 UB。调试时建议加 assert:

assert(first != last && "heap op on empty range");

实际项目里,如果排序是唯一目标,直接用 std::sort 更快更稳;STL 堆函数真正价值在于需要动态维护堆结构的场景,比如优先队列底层、Top-K 流式计算——这时候才轮到 push_heap/pop_heap 上场。


# c++  # 排列  # 为什么  # less  # sort  # const  # bool  # Lambda  #   # Struct  # operator  # 对象  # 升序  # 大堆  # 迭代  # 这一  # 是个  # 好了  # 降序  # 你有  # 而不  # 仍是 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何在Windows服务器上快速搭建网站?  Laravel Blade模板引擎语法_Laravel Blade布局继承用法  php中::能调用final静态方法吗_final修饰静态方法调用规则【解答】  JavaScript Ajax实现异步通信  如何在建站宝盒中设置产品搜索功能?  免费网站制作appp,免费制作app哪个平台好?  jquery插件bootstrapValidator表单验证详解  EditPlus中的正则表达式实战(5)  javascript如何操作浏览器历史记录_怎样实现无刷新导航  Laravel如何实现用户注册和登录?(Auth脚手架指南)  node.js报错:Cannot find module &#39;ejs&#39;的解决办法  Android GridView 滑动条设置一直显示状态(推荐)  Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案  Laravel Admin后台管理框架推荐_Laravel快速开发后台工具  Laravel如何使用Service Provider注册服务_Laravel服务提供者配置与加载  如何基于PHP生成高效IDC网络公司建站源码?  html5如何设置样式_HTML5样式设置方法与CSS应用技巧【教程】  如何用西部建站助手快速创建专业网站?  php json中文编码为null的解决办法  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  如何快速搭建高效WAP手机网站?  Laravel怎么生成二维码图片_Laravel集成Simple-QrCode扩展包与参数设置【实战】  JS中对数组元素进行增删改移的方法总结  浅谈redis在项目中的应用  如何在 Pandas 中基于一列条件计算另一列的分组均值  javascript基本数据类型及类型检测常用方法小结  东莞专业网站制作公司有哪些,东莞招聘网站哪个好?  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  实例解析Array和String方法  Python自动化办公教程_ExcelWordPDF批量处理案例  Laravel观察者模式如何使用_Laravel Model Observer配置  如何批量查询域名的建站时间记录?  如何在景安服务器上快速搭建个人网站?  EditPlus中的正则表达式实战(6)  如何快速查询域名建站关键信息?  如何快速登录WAP自助建站平台?  大同网页,大同瑞慈医院官网?  Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】  青岛网站建设如何选择本地服务器?  Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制  如何快速搭建FTP站点实现文件共享?  Laravel怎么实现模型属性转换Casting_Laravel自动将JSON字段转为数组【技巧】  Laravel如何发送系统通知?(Notification渠道示例)  Laravel如何使用Blade组件和插槽?(Component代码示例)  Laravel如何实现本地化和多语言支持?(i18n教程)  Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  Laravel如何与Pusher实现实时通信?(WebSocket示例)  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?