图解合并排序(归并排序)

 

我们用个简单的例子来看看这是什么意思:

通过此图你可以看到,在 2 个 4元素序列里你只需要迭代一次,就能构建最终的8元素已排序序列,因为两个4元素序列已经排好序了:

  • 1) 在两个序列中,比较当前元素(当前=头一次出现的第一个)
  • 2) 然后取出最小的元素放进8元素序列中
  • 3) 找到(两个)序列的下一个元素,(比较后)取出最小的
  • 重复1、2、3步骤,直到其中一个序列中的最后一个元素
  • 然后取出另一个序列剩余的元素放入8元素序列中。

这个方法之所以有效,是因为两个4元素序列都已经排好序,你不需要再『回到』序列中查找比较。

【译者注:合并排序详细原理。】

  

合并排序是把问题拆分为小问题,通过解决小问题来解决最初的问题(注:这种算法叫分治法,即『分而治之、各个击破』)。如果你不懂,不用担心,我第一次接触时也不懂。如果能帮助你理解的话,我认为这个算法是个两步算法:

  • 拆分阶段,将序列分为更小的序列
  • 排序阶段,把小的序列合在一起(使用合并算法)来构成更大的序列

拆分阶段

 

在拆分阶段过程中,使用3个步骤将序列分为一元序列。步骤数量的值是 log(N) (因为 N=8, log(N)=3)。

底数为2,道理是每一步都把原序列的长度除以2,步骤数就是你能把原序列长度除以2的次数。这正好是对数的定义(在底数为2时)。

 

排序阶段

在排序阶段,你从一元序列开始。在每一个步骤中,你应用多次合并操作,成本一共是 N=8 次运算。

  • 第一步,4 次合并,每次成本是 2 次运算。
  • 第二步,2 次合并,每次成本是 4 次运算。
  • 第三步,1 次合并,成本是 8 次运算。

因为有 log(N) 个步骤,整体成本是 N*log(N) 次运算

 

合并排序的强大之处

为什么这个算法如此强大?

因为:

  • 你可以更改算法,以便于节省内存空间,方法是不创建新的序列而是直接修改输入序列。

注:这种算法叫『原地算法』(in-place algorithm)

  • 你可以更改算法,以便于同时使用磁盘空间和少量内存而避免巨量磁盘 I/O。方法是只向内存中加载当前处理的部分。在仅仅100MB的内存缓冲区内排序一个几个GB的表时,这是个很重要的技巧。

注:这种算法叫『外部排序』(external sorting)。

  • 你可以更改算法,以便于在 多处理器/多线程/多服务器 上运行。

比如,分布式合并排序是Hadoop(那个著名的大数据框架)的关键组件之一。

 

这个排序算法在大多数(如果不是全部的话)数据库中使用,但是它并不是唯一算法。如果你想多了解一些,你可以看看 这篇论文,探讨的是数据库中常用排序算法的优势和劣势。

 

伪代码 

 1 array mergeSort(array a)
 2    if(length(a)==1)
 3       return a[0];
 4    end if
 5 
 6    //recursive calls
 7    [left_array right_array] := split_into_2_equally_sized_arrays(a);
 8    array new_left_array := mergeSort(left_array);
 9    array new_right_array := mergeSort(right_array);
10 
11    //merging the 2 small ordered arrays into a big one
12    array result := merge(new_left_array,new_right_array);
13    return result;

 

posted @ 2018-03-09 21:03  eel808  阅读(890)  评论(0编辑  收藏  举报