链表的归并排序 特殊优化, merge sort for list,非快慢指针法

来源:互联网 发布:php管理系统 编辑:程序博客网 时间:2024/06/01 09:37

list的归并排序不同于数组,因为list需要一步一步遍历,所以获取一个一个的区段是比较麻烦的

常见的实现办法是使用快慢指针找到中间点,再用自上而下的归并排序


但是这种方法需要一步一步遍历来找到中点。


今天再翻了一下《STL源码剖析》,偶然看到list的排序部分。发现书中那版stl采用了一种另类的list归并排序。

归并排序的主要思想在于分治,再合并。

通常对于数组的merge,可以自上而下或者自下而上,都很方便。

但是对于list,遍历只能一步一步。所以采用数组的merge sort方式就有些浪费。

书中给出了一种不需要寻找中点的merge 方式。

直接从list头开始一个一个拿,用类似2048游戏的方式,逐渐积累。

(其实可以看作一种二进制拆分。)

(联想到,利用斐波那契数列的查找?,对比二分查找)


具体做法,举个例子:

对于一个list,先拿出一个node,这算是一个1个节点的排序好的list。

然后再拿出来一个,也是一个1节点的list,可以和之前的merge,得到2个节点的。

再拿一个,这时候之前的是2节点,现在的是1节点,所以以归并排序的思想,不要merge。(实际上强行merge,就退化成了插排)

再拿一个,和之前的1节点merge,得到2节点。再和之前的2节点merge,得到四节点。

。。。重复以上。


实际上这种merge方式也不算太诡异。。Sedgewick的网上公开课讲merge的时候好像展示过这种方式。

但是因为对于数组,实现上没有自上而下和自下而上方便,又没有特别大的优势(数组找中点很直接),所以都被人忘了。。

但是用在list这里就刚刚好。



顺便说一句。看了我电脑上这版stl,没有用上述做法,而是一步一步遍历得到mid,再正常merge


代码后补



原创粉丝点击