0

0

c++中如何实现归并排序_c++归并排序详解

冰火之心

冰火之心

发布时间:2026-01-05 18:02:21

|

403人浏览过

|

来源于php中文网

原创

归并排序核心是分治且非原地排序,需额外空间合并子数组;递归版有栈溢出风险,应设终止条件并小数组转插入排序;迭代版更安全但边界易错;泛化需适配迭代器与移动语义。

c++中如何实现归并排序_c++归并排序详解

归并排序的核心逻辑是分治,不是原地排序

归并排序在 C++ 中必须额外分配空间来合并两个有序子数组,这点和 std::sort(通常是 introsort)有本质区别。如果你试图“原地归并”,会陷入高复杂度的旋转操作,实际项目中几乎没人这么做。标准实现依赖一个临时缓冲区,大小至少为待排序区间的长度。

递归写法要注意溢出风险

对百万级元素递归调用 mergeSort 可能导致栈溢出,尤其在默认栈大小的 Windows 或嵌入式环境。常见错误是没设递归终止条件或忽略小数组优化:

  • 必须检查 left >= right 作为递归基
  • 建议在子数组长度 ≤ 16 时切换到插入排序(std::sort 内部也这么干)
  • 避免每次递归都 new/delete 临时数组;应一次性分配好,传引用复用
void merge(std::vector& arr, std::vector& temp, int left, int mid, int right) {
    int i = left, j = mid + 1, k = left;
    while (i <= mid && j <= right) {
        if (arr[i] <= arr[j]) temp[k++] = arr[i++];
        else temp[k++] = arr[j++];
    }
    while (i <= mid) temp[k++] = arr[i++];
    while (j <= right) temp[k++] = arr[j++];
    for (i = left; i <= right; ++i) arr[i] = temp[i];
}

迭代版更安全,但容易写错区间边界

迭代归并避免递归开销,适合大数组或栈受限场景,但 for 循环里控制子数组长度(width)、起始点(left)、中点(mid)和终点(right)极易越界。典型错误包括:

  • mid = min(left + width - 1, n - 1) 忘记取 min,导致 mid >= n
  • right = min(left + 2 * width - 1, n - 1) 没加保护,合并时访问非法内存
  • 临时数组未覆盖整个 [left, right] 区间,造成部分数据未更新
void mergeSortIterative(std::vector& arr) {
    int n = arr.size();
    std::vector temp(n);
    for (int width = 1; width < n; width *= 2) {
        for (int left = 0; left < n - width; left += 2 * width) {
            int mid = std::min(left + width - 1, n - 1);
            int right = std::min(left + 2 * width - 1, n - 1);
            merge(arr, temp, left, mid, right);
        }
    }
}

STL 容器适配要考虑迭代器和移动语义

若想把归并排序泛化到任意容器(如 std::liststd::deque),不能直接索引,得用迭代器 + std::distancestd::advance。但注意:std::list 的随机访问是 O(n),强行套用数组版归并会退化成 O(n² log n)。更合理的方式是利用 std::list::merge —— 它本身就是稳定、O(n) 的归并操作。

mage.space
mage.space

AI图像内容生成工具

下载

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

对支持移动语义的类型(如 std::string、自定义类),记得在拷贝到 temp 时用 std::move,否则可能触发深拷贝:

temp[k++] = std::move(arr[i++]);

归并排序真正难的不是写出来,而是根据数据规模、内存限制、容器类型和元素开销,选对实现路径——递归/迭代、临时空间复用策略、是否启用移动、以及何时交给 std::sort 更省事。

相关专题

更多
string转int
string转int

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

314

2023.08.02

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

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

381

2023.09.04

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

380

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

566

2023.08.10

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

268

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.12.29

windows查看端口占用情况
windows查看端口占用情况

Windows端口可以认为是计算机与外界通讯交流的出入口。逻辑意义上的端口一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。怎么查看windows端口占用情况呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

552

2023.07.26

查看端口占用情况windows
查看端口占用情况windows

端口占用是指与端口关联的软件占用端口而使得其他应用程序无法使用这些端口,端口占用问题是计算机系统编程领域的一个常见问题,端口占用的根本原因可能是操作系统的一些错误,服务器也可能会出现端口占用问题。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1078

2023.07.27

漫蛙2入口地址合集
漫蛙2入口地址合集

本专题整合了漫蛙2入口汇总,阅读专题下面的文章了解更多详细内容。

13

2026.01.06

热门下载

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

精品课程

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

共48课时 | 6.7万人学习

Excel 教程
Excel 教程

共162课时 | 10.9万人学习

PHP基础入门课程
PHP基础入门课程

共33课时 | 1.9万人学习

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

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