zoukankan      html  css  js  c++  java
  • erlang下lists模块sort(排序)方法源码解析(二)

    上接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的代码比较多,看一下发现其实思路非常清晰,

    1 rmergel([[H3 | T3], [H2 | T2], T1 | L], Acc) ->
    2     rmergel(L, [rmerge3_1(T1, [], H2, T2, H3, T3) | Acc]);
    3 rmergel([[H2 | T2], T1], Acc) ->
    4     mergel([rmerge2_1(T1, H2, T2, []) | Acc], []);
    5 rmergel([L], Acc) ->
    6     mergel([lists:reverse(L, []) | Acc], []);
    7 rmergel([], Acc) ->
    8     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).

    查看对比结果

     1 95> timer:tc(tt1, mysort, [B2]).
     2 {48842,
     3  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,
     4   23,24,25,26,27|...]}
     5 96> timer:tc(tt1, mysort, [B2]).
     6 {53618,
     7  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,
     8   23,24,25,26,27|...]}
     9 97> timer:tc(lists, sort, [B2]).
    10 {31179,
    11  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,
    12   23,24,25,26,27|...]}
    13 98> timer:tc(lists, sort, [B2]).
    14 {29326,
    15  [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,
    16   23,24,25,26,27|...]}

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

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

  • 相关阅读:
    JavaScript高度和宽度详解
    VC6程序图标
    VC++中的Dlg,App,Doc,view
    Vista桌面图标无法拖动
    VC2008中IE8脚本错误问题解决
    单文件安装包制作(转)
    AutoResetEvent与ManualResetEvent区别
    纯JavaScript中调用WebServices
    动态加载程序集Assembly.Load
    VC++小知识积累
  • 原文地址:https://www.cnblogs.com/tudou008/p/9078302.html
Copyright © 2011-2022 走看看