商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > c++如何实现内存数据的快速排序并存入文件【技巧】

c++如何实现内存数据的快速排序并存入文件【技巧】

  发布于2026-07-17 阅读(0)

扫一扫,手机访问

先说几个核心判断:在C++里做内存数据排序再写文件,很多人第一反应是手写快排,但这事儿其实有更稳妥高效的路径。直接用 std::sort 就好,别自己折腾递归快排了——它底层是 introsort,混合了快排、堆排和插入排序,对小数组自动切到插入排序,对退化情况自动切到堆排,平均和最坏都是 O(n log n),而且高度优化、内联友好、缓存局部性好。自己手写的递归快排容易栈溢出,三数取中不全的话,还可能被恶意数据卡成 O(n²),得不偿失。

c++如何实现内存数据的快速排序并存入文件【技巧】

std::sort 为什么比手写快排更值得用

从实践来看,关键点在于:

  • 确保数据在连续内存中(比如 std::vector 或裸指针数组),std::sort 对随机访问迭代器效率最高
  • 若元素较大,比如含字符串或指针的结构体,优先按 key 排序:std::sort(v.begin(), v.end(), [](const auto& a, const auto& b) { return a.id < b.id; })
  • 避免在排序时频繁调用虚函数或锁——这些会破坏分支预测,拖慢 2–3 倍

写文件前先 reserve + resize 避免反复 realloc

如果排序后要写入二进制文件,比如 std::vector 全量 dump,别边排序边 push_back,更别用 std::ofstream << 格式化输出——那会把每个数转成字符串再写,慢一个数量级。正确的做法是:

  • 排序前确认容量:v.reserve(n); v.resize(n);,避免中间扩容拷贝
  • 二进制写入用 write()out.write(reinterpret_cast(v.data()), v.size() * sizeof(int));
  • 务必检查 out.good()!out,磁盘满或权限不足时 write() 不抛异常,只置 failbit

大数组(>100MB)要分块排序+归并,别硬塞进内存

当数据远超物理内存时,比如 1GB 数据在 512MB 内存机器上,std::sort 会触发大量 swap,IO 成瓶颈,速度暴跌。这时得用外部排序:分段读入 → 排序 → 写临时文件 → 多路归并。具体建议:

  • 每块大小设为可用内存的 70%,留余地给归并缓冲区,例如 400MB 内存就取 280MB 块
  • 临时文件命名加序号(tmp_001.bin, tmp_002.bin),避免冲突;用 std::tmpfile() 更安全但不可跨进程
  • 归并时用最小堆(std::priority_queue)管理各块首元素,每次取最小值写入主文件,再从对应块加载下一个

fstream 默认不缓冲,记得 setbuf 或用 mmap 加速写入

std::ofstream 默认使用小缓冲区(通常 8KB),对大块数据写入极其低效——每写几次就 flush 一次系统调用。而 mmap 在 Linux/macOS 上可绕过 stdio 缓冲,直接映射文件页写入,吞吐接近内存拷贝。实操建议:

  • 手动设置大缓冲:char buf[1<<20]; out.rdbuf()->pubsetbuf(buf, sizeof(buf));(注意必须在 open 前调用)
  • Linux 下用 mmap(需 ):先 ftruncate 扩容,再 mmap(nullptr, size, PROT_WRITE, MAP_SHARED, fd, 0),然后 memcpy 排序后数据过去,最后 msyncmunmap
  • Windows 用 CreateFileMapping + MapViewOfFile,原理相同,但 API 更啰嗦

真正卡住性能的往往不是排序算法本身,而是内存布局是否连续、文件写入是否绕过低效缓冲、以及大数组有没有触发 swap——这些点漏掉一个,提速 10 倍的排序就白做了。

本文转载于:https://www.php.cn/faq/2334500.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注