0. 简介

本文简要介绍一下比传统MergeSort更高效的算法,在原来的算法Merge基础上,少发生一半拷贝。欢迎探讨,感谢阅读。

原文链接如下:http://loverszhaokai.com/posts/More-Efficient-MergeSort/

1. Reference

原文链接

Introuction to Algorithms

https://github.com/loverszhaokai/ALG/blob/master/src/sort.cc

2. MergeSort

  1. void merge(int a[], int b[], const int left, const int middle,
  2. const int right) {
  3. int li, ri, i;
  4. li = left;
  5. ri = middle + 1;
  6. i = 0;
  7. while (li <= middle && ri <= right) {
  8. if (a[li] < a[ri])
  9. b[i++] = a[li++];
  10. else
  11. b[i++] = a[ri++];
  12. }
  13. while (li <= middle)
  14. b[i++] = a[li++];
  15. while (ri <= right)
  16. b[i++] = a[ri++];
  17. }
  18. void copy(int dst[], int dleft, int src[], int sleft, int sright) {
  19. memcpy(dst + dleft, src + sleft,
  20. sizeof(int) * (sright - sleft + 1));
  21. }
  22. void _merge_sort(int a[], int b[], const int left, const int right) {
  23. if (left >= right)
  24. return;
  25. int middle = (left + right) / 2;
  26. _merge_sort(a, b, left, middle);
  27. _merge_sort(a, b, middle + 1, right);
  28. merge(a, b, left, middle, right);
  29. copy(a, left, b, 0, right - left);
  30. }
  31. void merge_sort(int a[], const int size) {
  32. int *b = (int *)malloc(size * sizeof(int));
  33. _merge_sort(a, b, 0, size - 1);
  34. free(b);
  35. }

3. More Efficient MergeSort

We can save some time by copy half when merge(). In merge(), we copy from

left to right, but in MergeKai() we can only copy from left to

middle. The merge() has NlgN duplications which the MergeKai() has

1/2 * NlgN duplications.

  1. normal merge sort

  1. more efficient merge sort

Just as the previous example, the efficient merge sort does not need to copy

1, 3, 7, 8 to the assit array.

  1. // Merge the two list in [left, mid], and (mid, right]. Then, write
  2. // the result to [left, right]
  3. static void MergeKai(int a[], int assist[], const int left,
  4. const int mid, const int right) {
  5. int l = left;
  6. int r = mid + 1;
  7. int assist_index = 0;
  8. // Copy [left, mid] to assit[0, mid - left]
  9. memcpy(assist, a + left, (mid - left + 1) * sizeof(int));
  10. while (assist_index <= mid - left && r <= right) {
  11. if (assist[assist_index] <= a[r]) {
  12. a[l++] = assist[assist_index++];
  13. continue;
  14. } else if (assist[assist_index] > a[r]) {
  15. a[l++] = a[r++];
  16. }
  17. }
  18. while (assist_index <= mid - left) {
  19. a[l++] = assist[assist_index++];
  20. }
  21. while (r <= right) {
  22. a[l++] = a[r++];
  23. }
  24. }
  25. static void MergeSortKaiImpl(int a[], int assist[], const int left,
  26. const int right) {
  27. if (left >= right) {
  28. return;
  29. }
  30. const int mid = (left + right) / 2;
  31. MergeSortKaiImpl(a, assist, left, mid);
  32. MergeSortKaiImpl(a, assist, mid + 1, right);
  33. MergeKai(a, assist, left, mid, right);
  34. }
  35. void MergeSortKai(int a[], const int size) {
  36. int* assist= (int *)malloc(size * sizeof(int));
  37. MergeSortKaiImpl(a, assist, 0, size - 1);
  38. free(assist);
  39. }

4. Experiments

source:

https://github.com/loverszhaokai/ALG/blob/master/src/sort.cc

https://github.com/loverszhaokai/ALG/blob/master/test/sort_test.cc

result:

  1. It takes 1524.61 ms to generate arrays: 1000000 * 20
  2. Sort Function Total Run Time Array Size
  3. ---------------------------------------------------------------------
  4. merge_sort_iteratively 826 ms 1000000 * 20
  5. merge_sort 840 ms 1000000 * 20
  6. MergeSortIterativelyKai 826 ms 1000000 * 20
  7. MergeSortKai 809 ms 1000000 * 20
  8. It takes 15028.2 ms to generate arrays: 10000000 * 20
  9. Sort Function Total Run Time Array Size
  10. ---------------------------------------------------------------------
  11. merge_sort_iteratively 8717 ms 10000000 * 20
  12. merge_sort 8820 ms 10000000 * 20
  13. MergeSortIterativelyKai 8425 ms 10000000 * 20
  14. MergeSortKai 8389 ms 10000000 * 20
  15. It takes 1929.31 ms to generate arrays: 100000 * 200
  16. Sort Function Total Run Time Array Size
  17. ---------------------------------------------------------------------
  18. merge_sort_iteratively 1245 ms 100000 * 200
  19. merge_sort 1347 ms 100000 * 200
  20. MergeSortIterativelyKai 1246 ms 100000 * 200
  21. MergeSortKai 1275 ms 100000 * 200

更高效的MergeSort--稍微优化的更多相关文章

  1. 使jQuqer更高效的方法

    讨论 jQuery 和 javascript 性能的文章并不罕见.然而,本文我计划总结一些速度方面的技巧和我本人的一些建议,来提升你的 jQuery 和 javascript 代码.好的代码会带来速度 ...

  2. 如何使代码审查更高效【摘自InfoQ】

      代码审查者在审查代码时有非常多的东西需要关注.一个团队需要明确对于自己的项目哪些点是重要的,并不断在审查中就这些点进行检查. 人工审查代码是十分昂贵的,因此尽可能地使用自动化方式进行审查,如:代码 ...

  3. 如何让windows更高效?

    首先解释一下个标题: "让windows更高效,既指让windows更友好更优化,也指可以让使用windows来工作或学习的人更高效的工作学习." 解释下本文的动机: 指导我自己或 ...

  4. 更强、更稳、更高效:解读 etcd 技术升级的三驾马车

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 陈星宇(宇慕 ...

  5. CesiumLab V1.4 分类3dtiles生成(倾斜单体化、楼层房间交互)我记得我是写过一篇关于倾斜单体化的简书文章的,但是现在找不到了。不过找不到也好,就让他随风逝去吧,因为当时我写那篇文章的时候,就发现了cesium实际是有另一种更高效的单体化。就下面这个示例https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/index.html?src=

    我记得我是写过一篇关于倾斜单体化的简书文章的,但是现在找不到了.不过找不到也好,就让他随风逝去吧,因为当时我写那篇文章的时候,就发现了cesium实际是有另一种更高效的单体化.就下面这个示例 http ...

  6. [源码解析]为什么mapPartition比map更高效

    [源码解析]为什么mapPartition比map更高效 目录 [源码解析]为什么mapPartition比map更高效 0x00 摘要 0x01 map vs mapPartition 1.1 ma ...

  7. 阿里面试:MySQL如何设计索引更高效?

    有情怀,有干货,微信搜索[三太子敖丙]关注这个不一样的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文章. ...

  8. K8s 如何提供更高效稳定的编排能力?K8s Watch 实现机制浅析

    关于我们 更多关于云原生的案例和知识,可关注同名[腾讯云原生]公众号~ 福利: ①公众号后台回复[手册],可获得<腾讯云原生路线图手册>&<腾讯云原生最佳实践>~ ②公 ...

  9. Karmada v1.3:更优雅 更精准 更高效

    摘要:最新发布的1.3版本中,Karmada重新设计了应用跨集群故障迁移功能,实现了基于污点的故障驱逐机制,并提供平滑的故障迁移过程,可以有效保障服务迁移过程的连续性(不断服). 本文分享自华为云社区 ...

随机推荐

  1. Openstack的网卡设置

    本博客已经添加"打赏"功能,"打赏"位置位于右边栏红色框中,感谢您赞助的咖啡. 最开始接触Openstack,这块是比较头疼的,不同的文档,设置都会有所差异,并 ...

  2. wireshark 表达式备忘录

    参考资料: https://blog.csdn.net/wojiaopanpan/article/details/69944970 wireshark分两种表达式,一种是捕获表达式,这个是在捕获时用的 ...

  3. powerDesigner根据sql脚本来逆向生成pdm等模型

    一.问题概述 网上一般的博文都是说要建立数据源的方式来逆向或者正向. 我这人比较懒得折腾,更喜欢通过sql脚本的方式来做. 二.步骤 File-->New Model--> 然后: 注意上 ...

  4. 调用TerminateProcess是无法触发DLL_PROCESS_DETACH的

    当应用程序中调用TerminateProcess函数,对于在DllMain函数中处理DLL_PROCESS_DETACH的额外代码操作是无法被执行的.比如:释放资源.数据持久化等.

  5. MySQL知识小结

    MySQL的知识面试中还是经常被问到的,简单的使用似乎无法达到面试官的要求,很多问题会关于Mysql存储引擎,所以这里还是需要系统学习一下Mysql的一些知识,面试过程中游刃有余. MySQL体系结构 ...

  6. Unity3D笔记十八 GL图像库

    1.绘制2D图像的时需要使用GL.LoadOrtho()方法来将图形映射到平面中. 2.所有绘制相关的内容都要写在OnPostRender()方法中. 3.有关GL图像库的脚本需要绑定到Hierarc ...

  7. Node复制文件

    本人开发过程中,经常遇到,要去拷贝模板到当前文件夹,经常要去托文件,为了省事,解决这个问题,写了一个node复制文件. // js/app.js:指定确切的文件名.// js/*.js:某个目录所有后 ...

  8. [转][darkbaby]任天堂传——失落的泰坦王朝(中)

    TV游戏产业历史上曾有过太多表里不一的外交辞令,然而当年SQUARE和任天堂分道扬镳的真正原因确实如坂口博信在1996年2月29日的PS版 <FFVII>发表会上宣称的那样:“虽然之前有过 ...

  9. 2-sat入门(tarjan)hdu(3062)

    hdu3062 Party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  10. 小程序中的block

    <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性. 因为 wx:if 是一个控制属性,需要将它添加到一个标签上.如果要一次性判断多个组件标签, ...