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的代码比较多,看一下发现其实思路非常清晰,
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(排序)方法源码解析(二)的更多相关文章
- erlang下lists模块sort(排序)方法源码解析(一)
排序算法一直是各种语言最简单也是最复杂的算法,例如十大经典排序算法(动图演示)里面讲的那样 第一次看lists的sort方法的时候,蒙了,几百行的代码,我心想要这么复杂么(因为C语言的冒泡排序我记得不 ...
- Mybatis源码解析(二) —— 加载 Configuration
Mybatis源码解析(二) -- 加载 Configuration 正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...
- RxJava2源码解析(二)
title: RxJava2源码解析(二) categories: 源码解析 tags: 源码解析 rxJava2 前言 本篇主要解析RxJava的线程切换的原理实现 subscribeOn 首先, ...
- Sentinel源码解析二(Slot总览)
写在前面 本文继续来分析Sentinel的源码,上篇文章对Sentinel的调用过程做了深入分析,主要涉及到了两个概念:插槽链和Node节点.那么接下来我们就根据插槽链的调用关系来依次分析每个插槽(s ...
- TreeSet集合的add()方法源码解析(01.Integer自然排序)
>TreeSet集合使用实例 >TreeSet集合的红黑树 存储与取出(图) >TreeSet的add()方法源码 TreeSet集合使用实例 package cn.itca ...
- jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究
终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...
- 解析jQuery中extend方法--源码解析以及递归的过程《二》
源码解析 在解析代码之前,首先要了解extend函数要解决什么问题,以及传入不同的参数,会达到怎样的效果.extend函数内部处理传入的不同参数,返回处理后的对象. extend函数用来扩展对象,增加 ...
- Spring源码解析二:IOC容器初始化过程详解
IOC容器初始化分为三个步骤,分别是: 1.Resource定位,即BeanDefinition的资源定位. 2.BeanDefinition的载入 3.向IOC容器注册BeanDefinition ...
- ArrayList源码解析(二)
欢迎转载,转载烦请注明出处,谢谢. https://www.cnblogs.com/sx-wuyj/p/11177257.html 自己学习ArrayList源码的一些心得记录. 继续上一篇,Arra ...
随机推荐
- vue评论显示隐藏,JavaScript显示关闭
<template> <div id="vue_det"> <h1>{{details()}}</h1> <div>{{ ...
- django--orm对象关系映射之常用的增删改查
1.查询表里所有数据 book=models.Book.objects.all() 2.条件查询 book = models.Book.objects.filter(id=1).first() # 查 ...
- sql server中的while循环语句
语法格式: while 条件 begin ....... end declare @num begin update SDetail end
- Oracle创建表空间、表、一级用户授权
---恢复内容开始--- 1. 安装: 百度一下你就知道 2. sqlplus登录/sqlplus命令登录 在安装Oracle时,你需要记住设置的“全局数据库名”(默认为orcl) 和 口令,在以两种 ...
- sitecore8.2 基于相对路径查询item
当前项目: bar (path: /sitecore/content/home/foo/bar) 查询: query:./child/grandchild 结果: grandchild (path: ...
- CentOS7 配置ISCSI targetcli 共享存储
- Java-关于Thread
1)进程是受操作系统管理的基本运行单元,线程是进程中独立运行的子任务 2)Thread.start()方法通知线程规划器,告知其该线程已经准备完成,可以调用其run方法,这时就是异步的方法:如果直接调 ...
- python基础部分----基本数据类型
0.文章来源:http://www.cnblogs.com/jin-xin/articles/7562422.html 1.数字 2.bool 3.str字符串 3.1.字符串的索引与切片. 索引即下 ...
- psql 存储过程
--添加人员和虹膜注册信息 CREATE OR REPLACE FUNCTION AddPersonInfoAndIrisEnrollInfo(personName character, workSn ...
- docker组件介绍
一.Docker Client and Daemon(docker egine docker 引擎) docker是一个客户端工具,作用是发送 用户的请求给 dockerd 安装路径: /usr/bi ...