0

0

c++中堆排序算法如何实现_c++ heap sort代码【源码】

尼克

尼克

发布时间:2026-01-28 15:01:05

|

437人浏览过

|

来源于php中文网

原创

堆排序核心是heapify而非完整堆类实现,应优先使用std::make_heap和std::pop_heap原地排序,建堆O(n),需从下标(n/2)-1开始sift_down,且不稳定、缓存不友好。

c++中堆排序算法如何实现_c++ heap sort代码【源码】

堆排序的核心是 heapify 而不是手写完整二叉堆类

多数人误以为堆排序必须先实现一个完整的 Heap 类(带 insertextract_max 等),其实 C++ 标准库已提供底层支持,且原地排序只需关注 heapify 过程。关键在于:堆排序本质是「建堆 + 反复弹出最大值」,而建堆可以自底向上用 std::make_heap,或手动实现 sift_down 逻辑。

常见错误现象:std::make_heap 后直接遍历数组,发现顺序不对——因为它是最大堆,顶部是最大值,但整个数组不有序;必须配合 std::pop_heap 把最大值逐步移到末尾。

  • std::make_heap 时间复杂度 O(n),不是 O(n log n);这是很多人忽略的优化点
  • 若用 std::priority_queue 实现,会额外分配内存,失去「原地」优势
  • 手动实现 heapify 时,最后一个非叶子节点下标是 (n / 2) - 1,不是 n / 2

std::make_heapstd::pop_heap 组合实现最简版本

这是最贴近算法导论描述、又避免重复造轮子的做法。它不引入额外容器,只操作原始数组,且可复用标准库的健壮性。

void heap_sort(std::vector& arr) {
    std::make_heap(arr.begin(), arr.end());  // 建最大堆
    for (auto it = arr.end(); it != arr.begin(); --it) {
        std::pop_heap(arr.begin(), it);  // 把堆顶移到 [it-1]
    }
}

注意:std::pop_heap 不删除元素,只是把最大值换到当前范围末尾,然后调整剩余部分为堆。所以循环中 itend() 开始递减,每次缩小堆的范围。

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

  • 如果传入 std::vector,需确保有随机访问迭代器(满足)
  • 排序后是升序;若要降序,改用 std::less 作为第三个参数(默认是 std::less,即最大堆 → 升序)
  • int* 数组也适用:std::make_heap(ptr, ptr + n)

手动实现 sift_down 时索引边界容易错

当不用标准库、必须手写时,核心是 sift_down 函数:从某节点出发,将其下沉到合适位置。最容易出错的是左右孩子索引计算和越界判断。

Getimg.ai
Getimg.ai

getimg.ai是一套神奇的ai工具。生成大规模的原始图像

下载

假设当前节点下标为 i,则:

  • 左孩子: 2 * i + 1(不是 2 * i,因数组从 0 开始)
  • 右孩子: 2 * i + 2
  • 检查是否越界:必须同时满足 left 和 right ,不能只比 arr.size()
  • 下沉前要先比较左右孩子,选较大者再与父节点交换;否则可能破坏堆性质

建堆阶段必须从最后一个非叶子节点开始倒序调用 sift_down,否则无法保证整体堆结构。这个节点是 (arr.size() / 2) - 1,不是 arr.size() / 2arr.size() - 1

性能与稳定性:堆排序不适合小数组,也不稳定

堆排序时间复杂度稳定在 O(n log n),但常数因子比快排大;实际中,STL 的 std::sort 通常用 introsort(快排+堆排兜底),而非纯堆排。

  • 对少于 ~32 个元素的数组,插入排序更快;标准库实现通常会切分处理
  • 堆排序不稳定:相等元素的相对位置可能改变,比如用于结构体排序时要注意字段相等性
  • 缓存不友好:sift_down 的跳转访问模式导致 CPU cache miss 高于归并或快排

如果你真需要手写堆排序,优先考虑复用 std::make_heap + std::pop_heap;手动实现只在教学、嵌入式无 STL 或定制比较逻辑时才值得投入。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

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

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

203

2023.10.12

sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

391

2023.09.04

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

220

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

192

2025.07.04

string转int
string转int

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

443

2023.08.02

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

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

544

2024.08.29

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

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

73

2025.08.29

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

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

197

2025.08.29

俄罗斯Yandex引擎入口
俄罗斯Yandex引擎入口

2026年俄罗斯Yandex搜索引擎最新入口汇总,涵盖免登录、多语言支持、无广告视频播放及本地化服务等核心功能。阅读专题下面的文章了解更多详细内容。

134

2026.01.28

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 7.8万人学习

C 教程
C 教程

共75课时 | 4.2万人学习

C++教程
C++教程

共115课时 | 14.3万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号