上接erlang下lists模块sort(排序)方法源码解析(一),到目前为止,list列表已经被分割成N个列表,而且每个列表的元素是有序的(从大到小)

下面我们重点来看看mergel和rmergel模块,因为我们先前主要分析的split_1_*对应的是rmergel,我们先从rmergel查看,如下

.......................................................

split_1(X, Y, [], R, Rs) ->
   rmergel([[Y, X | R] | Rs], []).

.......................................................
split_1_1(X, Y, [], R, Rs, S) ->
rmergel([[S], [Y, X | R] | Rs], []).
.............................................................

rmergel的代码比较多,看一下发现其实思路非常清晰,

 rmergel([[H3 | T3], [H2 | T2], T1 | L], Acc) ->
rmergel(L, [rmerge3_1(T1, [], H2, T2, H3, T3) | Acc]);
rmergel([[H2 | T2], T1], Acc) ->
mergel([rmerge2_1(T1, H2, T2, []) | Acc], []);
rmergel([L], Acc) ->
mergel([lists:reverse(L, []) | Acc], []);
rmergel([], Acc) ->
mergel(Acc, []).

当列表的个数>=3超过就用拿3个进行比较合并rmerge3_1实现,把这3个列表拼成1个有序的列表(拼完成了从小到大);剩下的按照这个逻辑

当然列表=2就拿2个进行比较合并rmerge2_1实现,把这2个列表拼成1个有序的列表(拼完成了从小到大)

当列表只有1个的时候,这个列表就是有序的了

整个逻辑是这样的,当列表大于等于2个,先调用rmerge3_1,如果H1>=H2就调用rmerge3_21,否则就调用rmerge3_12,然后rmerge3_21如果H3>=H1就说明H3最大,然后继续比较

总得来说,就是把3个列表的第一个元素拿出来,比较,最大的放变量M里面,根据比较的顺序不同,使用不同的函数。

按照这个理解,复杂程度应该是log3n*n不是先前理解的n,

可是这里不能理解的是为什么要拿3个来比较,

我按照一次拿2个的逻辑来写,代码就简单很多,可是运行的时间差不多是原作者的的1.5-2倍,实在不能理解

附上我一次拿2个列表的逻辑代码

my_rmerge([H1,H2|T], R) ->
my_rmerge(T, [my_rmerge2(H1, H2, [])|R]);
my_rmerge([H1], R) ->
my_merge([lists:reverse(H1)|R], []);
my_rmerge([], [R]) ->
R;
my_rmerge([], R) ->
my_merge(R, []). my_rmerge2([H1|T1],[H2|T2], List) when H2 >= H1 ->
([H1|T1], T2, [H2|List]);
my_rmerge2([H1|T1],[H2|T2], List) ->
my_rmerge2(T1, [H2|T2], [H1|List]);
my_rmerge2([], L2, List) ->
lists:reverse(L2, List);
my_rmerge2(L1, [], List) ->
lists:reverse(L1, List). my_merge([H1,H2|T], R) ->
my_merge(T, [my_merge2(H1, H2, [])|R]);
my_merge([H1], R) ->
my_rmerge([lists:reverse(H1)|R], []);
my_merge([], [R]) ->
lists:reverse(R);
my_merge([], R) ->
my_rmerge(R, []). my_merge2([H1|T1],[H2|T2], List) when H2 < H1 ->
my_merge2([H1|T1], T2, [H2|List]);
my_merge2([H1|T1],[H2|T2], List) ->
my_merge2(T1, [H2|T2], [H1|List]);
my_merge2([], L2, List) ->
lists:reverse(L2, List);
my_merge2(L1, [], List) ->
lists:reverse(L1, List).

查看对比结果

 > timer:tc(tt1, mysort, [B2]).
{,
[,,,,,,,,,,,,,,,,,,,,,,
,,,,|...]}
> timer:tc(tt1, mysort, [B2]).
{,
[,,,,,,,,,,,,,,,,,,,,,,
,,,,|...]}
> timer:tc(lists, sort, [B2]).
{,
[,,,,,,,,,,,,,,,,,,,,,,
,,,,|...]}
> timer:tc(lists, sort, [B2]).
{,
[,,,,,,,,,,,,,,,,,,,,,,
,,,,|...]}

B2是一个1到100000的乱序列表,为什么差别会这么大,

有没有大神解释一下,按这样的逻辑,如果一次拿4个是不是更块,代码当然更多~~~

erlang下lists模块sort(排序)方法源码解析(二)的更多相关文章

  1. erlang下lists模块sort(排序)方法源码解析(一)

    排序算法一直是各种语言最简单也是最复杂的算法,例如十大经典排序算法(动图演示)里面讲的那样 第一次看lists的sort方法的时候,蒙了,几百行的代码,我心想要这么复杂么(因为C语言的冒泡排序我记得不 ...

  2. Mybatis源码解析(二) —— 加载 Configuration

    Mybatis源码解析(二) -- 加载 Configuration    正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...

  3. RxJava2源码解析(二)

    title: RxJava2源码解析(二) categories: 源码解析 tags: 源码解析 rxJava2 前言 本篇主要解析RxJava的线程切换的原理实现 subscribeOn 首先, ...

  4. Sentinel源码解析二(Slot总览)

    写在前面 本文继续来分析Sentinel的源码,上篇文章对Sentinel的调用过程做了深入分析,主要涉及到了两个概念:插槽链和Node节点.那么接下来我们就根据插槽链的调用关系来依次分析每个插槽(s ...

  5. TreeSet集合的add()方法源码解析(01.Integer自然排序)

    >TreeSet集合使用实例 >TreeSet集合的红黑树 存储与取出(图) >TreeSet的add()方法源码     TreeSet集合使用实例 package cn.itca ...

  6. jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究

    终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...

  7. 解析jQuery中extend方法--源码解析以及递归的过程《二》

    源码解析 在解析代码之前,首先要了解extend函数要解决什么问题,以及传入不同的参数,会达到怎样的效果.extend函数内部处理传入的不同参数,返回处理后的对象. extend函数用来扩展对象,增加 ...

  8. Spring源码解析二:IOC容器初始化过程详解

    IOC容器初始化分为三个步骤,分别是: 1.Resource定位,即BeanDefinition的资源定位. 2.BeanDefinition的载入 3.向IOC容器注册BeanDefinition ...

  9. ArrayList源码解析(二)

    欢迎转载,转载烦请注明出处,谢谢. https://www.cnblogs.com/sx-wuyj/p/11177257.html 自己学习ArrayList源码的一些心得记录. 继续上一篇,Arra ...

随机推荐

  1. Pyenv部署

    一.Git克隆方式 1.安装git yum -y install git 2.克隆pyenv到本地 git clone https://github.com/pyenv/pyenv.git ~/.py ...

  2. C#中的as关键字

    你能进到这篇文章…… 首先你可能明白类似于 double num=0;int m=(int) num; 或者你明白 int m=209;String str=m.toString();或者说你甚至见过 ...

  3. symfony command

    symfony 的command系统,有两部分构成:Application和command 1. Application是一个容器,负责对command进行管理. 2.command是每一个具体的命令 ...

  4. volatile CAS区别

  5. 问题 1672: 迷宫问题 (BFS)

    题目链接:https://www.dotcpp.com/oj/problem1672.html 问题 1672: 迷宫问题 时间限制: 1Sec 内存限制: 32MB 提交: 663 解决: 158 ...

  6. Caused by: java.lang.NoSuchMethodError: org.apache.poi.hssf.usermodel.HSSFCell.setEncoding(S)V

    java.lang.reflect.InvocationTargetException.  Coused by : java.lang.NoSuchMethodError:这个异常是找不到方法,但是如 ...

  7. spring boot+spring data jpa+gradle+mysql配置问题

    1.gradle/wrapper/gradle-wrapper里要设置正确本地的gradle目录(我用的是4) 2.在src目录里的application.properties文件里,可以这样设置 # ...

  8. post请求中body数据类型

    1.application/json:json格式,如下: {"input1":"xxx","input2":"ooo" ...

  9. opencv学习之路(41)、人脸识别

    一.人脸检测并采集个人图像 //take_photo.cpp #include<opencv2/opencv.hpp> using namespace cv; using namespac ...

  10. 2018年-2019年第二学期第三周C#学习个人总结

    在第三周,我们又开始了C#的进一步学习,学习的范围是从4.8static关键字到4.11对象初始化器.在4.8static关键字我学到了静态字段,静态属性,静态方法,静态类,静态构造方法单例模式,嵌套 ...