【连载】关系型数据库是如何工作的?(3) - 归并排序

当你需要对一个集合排序时,你会怎么做?什么?你会调用排序函数…好吧,也算个好答案…但是对于数据库来说,你必须理解这个排序函数是如何工作的?

有很多高效的排序算法,但让我们聚焦于最重要的一个:归并排序。你现在也许不太明白排序为什么很有用,但是到后续章节讲到查询排序你就会明白了。

归并

和很多有用的算法一样,归并排序其实是用于合并两个有序等长(N/2)数组,并且只需要N个操作。这个操作就被称为归并。让我们来看一个简单的例子:

归并排序

在上图中可以看到,因为初始的两个4元素数组是有序的,所以生成最终的8元素数组只需要遍历一次2个4元素数组。

  • 1)比较两个当前元素的当前元素(第一次就是0号元素);
  • 2)比较后较小的元素放入8元素数组;
  • 3)移动上次比较元素较小的数组的下标;
  • 重复以上3步,直到到达某一个数组的最大下标;
  • 然后把另外一个数组的剩余元素都放入最终数组的尾部。

现在我们理解了归并排序的思想,伪代码如下:

array mergeSort(array a)
   if(length(a)==1)
      return a[0];
   end if

   //recursive calls
   [left_array right_array] := split_into_2_equally_sized_arrays(a);
   array new_left_array := mergeSort(left_array);
   array new_right_array := mergeSort(right_array);

   //merging the 2 small ordered arrays into a big one
   array result := merge(new_left_array,new_right_array);
   return result;

译者批注:原作的伪代码个人认为不太直观,因此采用Java风格重写了一段实现:

int[4] array_a = {1, 5, 6, 7};
int[4] array_b = {2, 3, 4, 8};
int[8] array_result = {};

for(int i=0, int j=0, int k=0;i < 4, j < 4, k < 8;) {
    if(array_a[i] <= array_b[j]) {
        array_result[k] = array_a[i];
        i++;
        k++;
    } else {
        array_result[k] = array_b[j];
        j++;
        k++;
    }
}

归并排序实际上是把一个大问题拆分成一个一个的小问题,解决每一个小问题最终就可以得到大问题的答案。(译者批注:有没有感觉和MapReduce的思想一模一样呢,其实这是我们解决规模比较大的复杂问题的常用手段和技巧)如果你还没有理解归并排序,不必担心,笔者第一次见到这个算法也不理解。我想将其看成一个两阶段算法对于彻底理解它会很有帮助:

  • 1)拆分阶段:将一个大的数组划分为一个一个的小数组;
  • 2)排序阶段:将每一个小数组合并成为一个大数组;

拆分阶段

拆分

在拆分阶段,用3(因为log(8)=3)步就可以将大数组拆分为8个单元素数组。
我是怎么知道的?很简单,我是上帝咯!(译者说明:笔者好幽默)其实是靠数学计算,其思想其实就是按照2分法拆分原始数组,这就是精确的算法定义。

排序阶段

排序

在排序阶段,你可以通过8步将全部的单元素数组合并为一个大小为N的大数组。

  • 在第一步,你将做4次合并,每次合并包含2次操作;
  • 在第二步,你将做2次合并,每次合并包含4次操作;
  • 在第三步,你将做1次合并,每次合并包含8次操作;

因此,整个过程包括3步(log(N)),并且总共包含16次(N*log(N))操作。

归并排序的强大之处

为什么这个排序这么强大呢?因为:

  • 你可以修正它,用于降低内存占用,也就是说你无须创建新的数组就可以直接修改输入数组。(这种算法称为in-place
  • 你可以修正它,用磁盘空间和少量内存就可以避免大量的磁盘IO消耗。其思想是只加载当前正在处理的数据到内存,这很重要,当你只有很小的内存缓存但确要排序海量数据时。(这种算法称为external sorting
  • 你可以修正它,运行多个进程、线程和服务。比如:分布式排序就是Hadoop组件的核心。
  • 这个算法还可以点石成金。(译者说明:越简单的理论越重要,也越不容易过时

这个算法被用在绝大多数数据库中,但不是唯一被使用的排序算法。如果你想了解更多的排序算法,可以查阅这篇介绍各种数据库常用排序算法优缺点的论文

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值