0

0

c++中如何实现归并排序_c++分治思想归并排序算法【详解】

尼克

尼克

发布时间:2026-01-18 11:07:02

|

426人浏览过

|

来源于php中文网

原创

归并排序的核心是分治三步:split切分、merge合并、combine写回;merge需用临时数组、半开区间、正确边界控制,且应复用辅助空间而非重复分配。

c++中如何实现归并排序_c++分治思想归并排序算法【详解】

归并排序的核心逻辑是分治,不是递归本身

归并排序的正确理解起点不是“写个递归函数”,而是明确三步:split(切分到单元素)、merge(合并两个有序段)、combine(把合并结果写回原数组)。递归只是实现 split 的自然手段,但容易让人忽略 merge 的边界控制——这才是实际编码出错最多的地方。

  • 切分时用 [left, right) 半开区间比 [left, right] 更少出错,避免 mid = (left + right) / 2 溢出可改用 mid = left + (right - left) / 2
  • merge 必须用临时数组暂存结果,不能边合并边写回原数组,否则会覆盖未读取的数据
  • 合并循环的终止条件不是“两个子数组都空”,而是“至少一个已耗尽”,剩余部分直接拷贝

标准实现中 merge 函数的四个关键参数

很多初学者把 merge 写成只接受两个独立数组的函数,这在归并排序里反而增加复杂度。实际应传入原数组指针 + 三段下标:arrleftmidrightmid 是左半段末尾+1,即右半段起始位置)。

  • leftmid-1 是左有序段
  • midright-1 是右有序段
  • 合并结果要填回 arr[left]arr[right-1]
  • 临时数组大小必须是 right - left,而非固定长度或 arr.size()

避免内存重复分配的常见优化

每次递归都 new 临时数组会导致大量堆分配,尤其对大数组性能敏感。更合理的方式是在顶层调用时一次性分配好辅助空间,全程复用。

void mergeSort(vector& arr) {
    if (arr.size() <= 1) return;
    vector temp(arr.size()); // 一次分配
    mergeSortHelper(arr, temp, 0, arr.size());
}

void mergeSortHelper(vector& arr, vector& temp, int left, int right) { if (right - left <= 1) return; int mid = left + (right - left) / 2; mergeSortHelper(arr, temp, left, mid); mergeSortHelper(arr, temp, mid, right); merge(arr, temp, left, mid, right); }

  • temp 作为引用传入,避免拷贝
  • merge 内部只操作 temp 的对应区间,再批量拷贝回 arr
  • 若用原始指针(如 int*),需额外传入 temp 起始地址,逻辑不变

迭代版归并排序为什么更难写对

递归版天然体现分治结构,而迭代版靠自底向上合并:先两两合并长度为 1 的段,再合并长度为 2 的段……容易错在 right 边界越界和最后一段长度不足时的处理。

企奶奶
企奶奶

一款专注于企业信息查询的智能大模型,企奶奶查企业,像聊天一样简单。

下载

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

  • 外层循环步长 len 从 1 开始,每次翻倍:for (int len = 1; len
  • 内层循环起点 i 每次加 2 * len,但 right = min(i + 2 * len - 1, n - 1) 必须取最小值
  • 右半段可能不存在(i + len >= n),此时跳过合并
  • 即使知道原理,手写迭代版仍建议先跑通递归版,再对照改写,否则调试成本极高

归并排序真正卡住人的地方,从来不是“怎么分”,而是“合并时下标算错一格,整段结果就乱序”,尤其是 midright 的开闭关系、临时数组拷贝的起始偏移。写完务必用 {5, 2, 4, 7, 1} 这类小样例单步验证 merge 调用前后的子数组内容。

相关专题

更多
string转int
string转int

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

318

2023.08.02

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

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

538

2024.08.29

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

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

52

2025.08.29

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

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

197

2025.08.29

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

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

391

2023.07.18

堆和栈区别
堆和栈区别

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

572

2023.08.10

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

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

391

2023.07.18

堆和栈区别
堆和栈区别

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

572

2023.08.10

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

43

2026.01.16

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 3.6万人学习

Rust 教程
Rust 教程

共28课时 | 4.5万人学习

Git 教程
Git 教程

共21课时 | 2.8万人学习

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

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