Scala归并排序解析

一、源代码

def msort[T](xs:List[T])(lt: (T,T) => Boolen):List[T]={
	val n = xs.length  / 2
	if (  n == 0 ) xs
	else{
		def merge(xs: List[T],ys: List[T]):List[T] = (xs, ys) match{
			case(Nil, ys) => ys
			case(xs, Nil) => xs
			case(x:: xs1,y:: ys1)=>
				if(lt(x,y)) x::merge(xs,ys1)
				else y:: merge(xs,ys1)
		}
		val (fst,snd) = xs splitAt n
		merge(msort(fst)(lt),msort(snd)(lt))
	}
}

源代码来自Coursera 《Scala函数式编程原理》

其中,msort函数的第二个参数——lt: (T,T) => Boolen,它是一个自定义的谓词比较方法,用于比较T类型对象的大小,这里不做讨论。

二、示例

List元素:ls : List[Int]={7,4,15,43,9}

msort({7,4,15,43,9})
merge(msort({7,4,15}),msort({43,9}))
	对于msort({7,4,15})的递归
	=>merge(msort({7,4}),msort({15}))
		对于msort({7,4})的递归
		=>merge(msort({7}),msort({4}))
		=>merge(7,4)
	对于msort({43,9})的递归
	=>merge(msort({43}),msort({9}))
	=>merge(43,9)
merge(merge(msort({7,4}),msort({15})),merge(msort({43}),msort({9})))
merge(merge(merge(msort({7}),msort({4})),15),merge(43,9))
merge(merge(merge(7,4),15),merge(43,9))//这是一系列的拆分过程

拆分的图示:

上面是一个拆分过程,之后进行列表的两两合并:

每次合并后,都会形成有序的列表,所以问题转化成了——对两个有序的列表进行排序。回顾merge函数,它借用msort对参数进行分解。也就是说merge函数的两个列表参数一定是有序的——在merge函数体内,就是对两个列表有序列表进行合并排序的过程。

三、原理

1.将待排序的列表拆分成包含单个元素的列表

2.拆分的列表元素列表两两合并并排序,直到合并成一个列表。

四、递归函数的输入和输出

1. msort函数:传入一个待排序列表,输出一个排序后的列表。

2.merge函数:传入两个有序的列表,输出一个有序的列表。

五、递归的解释

程序中出现的递归有这几处:

1.merge函数的参数使用msort做了拆分的递归操作。

2.merge对两个参数进行排序使用了merge函数。这里的递归更像一种功能的重用——合并两个有序列表的功能。

递归的退出条件:

1.msort函数:待排序的列表只有一个元素或者为空列表

2.merge函数:两个参数中有一个为空列表

递归部分的处理:

msort使用merge函数返回一个有序列表

merge使用merge函数自身将两个有序列表进行合并

很明显,递归交由merge函数处理,也就是说,merge能够达到自身退出递归的条件—— 一直调用merge函数会形成,参数中只有一个列表的情况。所以,这里的msort函数只是提供了一个拆分的功能——辅助merge函数,将一个列表折半成两个列表的功能。

目前为止,重点就是merge函数合并两个有序列表的方法,这里通过提取出最小的一个元素,并merge剩下的元素来缩减,针对{4,7,15}和{9,43}的merge函数的递归合并过程如下图:

这就实现了对两个有序列表进行排序的过程。对于归并排序的总结就是两点:

1.使用msort对待排序的列表进行拆分,直到形成含单个元素的列表。

2.使用merge对两个有序列表进行合并,直到形成一个列表为止。

版权声明:随意评论。

时间: 2024-10-23 18:53:27

Scala归并排序解析的相关文章

scala语法解析(解码指环)

看惯了JAVA的语法,再看scala的语法,有的晦涩难懂.正好遇到一个介绍scala语法的文章,就直接截图留念.省的再临时抱佛脚了. scala语法解析(解码指环)

Scala重载解析

如果一个标识符或选择e引用了数个类的成员,则将使用引用的上下文来推断唯一的成员.使用的方法将依赖于e是否被用作一个函数.设A是e引用的成员的集合.首先假定e作为函数出现在应用中,比如e(args).如果在A中有且仅有一个可选成员是一个(可能是多态)方法类型,其元数与给出的参量数目匹配,则就会选定该可选成员.否则,设Ts是通过用未定义类型来类型化每个参量所得到的类型向量.首先要确定的是可用的可选成员的集合.如果Ts中每个类型都与对应的可选成员中正式参数类型相似,且如果期望类型已定义,方法的结果类型

大数据系列修炼-Scala课程06

关于Scala中的正则表达式与模式匹配结合的正则表达式Reg 正则表达式的实现:正则表达式的定义与其它语言差不多,只需在表达式后加一个.r,并且可以遍历相应的表达式进行匹配 //定义的正则表达式 val regex="""([0-9]+) ([a-z]+)""".r //由数字与字母组成的常量 val numPattern = "[0-9]+".r //由数字组成的常量 val numberPattern = "&q

深入研究Spark SQL的Catalyst优化器(原创翻译)

Spark SQL是Spark最新和技术最为复杂的组件之一.它支持SQL查询和新的DataFrame API.Spark SQL的核心是Catalyst优化器,它以一种新颖的方式利用高级编程语言特性(例如Scala的模式匹配和quasiquotes)来构建可扩展查询优化器. 我们最近发布了一篇关于Spark SQL的论文,该论文将出现在SIGMOD 2015(由Davies Liu,Joseph K. Bradley,Xiangrui Meng,Tomer Kaftan,Michael J. F

flink专题

一.Storm (一)什么是Storm? Storm为分布式实时计算提供了一组通用原语,可被用于“流处理”之中,实时处理消息并更新数据库.这是管理队列及工作者集群的另一种方式. Storm也可被用于“连续计算”(continuous computation),对数据流做连续查询,在计算时就将结果以流的形式输出给用户.它还可被用于“分布式RPC”,以并行的方式运行昂贵的运算. Storm可以方便地在一个计算机集群中编写与扩展复杂的实时计算,Storm用于实时处理,就好比 Hadoop 用于批处理.

2.12Java专项测试复盘

以下哪个接口的定义是正确的?( ) A. interface B { void print() { } ;} B. interface B { static void print() ;} C. abstract interface B extends A1, A2 //A1.A2为已定义的接口 { abstract void print(){ };} D. interface B { void print();} 解析:接口中方法的默认修饰符时public abstract,抽象方法可是没有方

2.20专项测试复盘

对于非运行时异常,程序中一般可不做处理,由java虚拟机自动进行处理. A. 正确 B. 错误 解析:运行异常,可以通过java虚拟机来自行处理.非运行异常,我们应该捕获或者抛出. 答案:B 下面哪些类可以被继承? Java.lang.Thread.java.lang.Number.java.lang.Double.java.lang.Math. java.lang.ClassLoader A. Thread B. Number C. Double D. Math E. ClassLoader

Java学习体系

一.JavaSE1.Java开发环境搭建2.Java基础语法3.Java面向对象4.异常5.数组/算法6.常用类7.集合/数据结构8.IO流9.线程10.反射机制11.网络编程12.注解Annotation13.MySQL初级14.JDBC 二.JavaWeb初级1.HTML/HTML52.CSS/CSS33.JavaScript4.jQuery5.Bootstrap6.XML+XPath7.Servlet8.Jsp9.EL10.JSTL11.Filter12.Listener13.Servle

使用Scala基于词法单元的解析器定制EBNF范式文法解析

一.前言 近期在做Oracle迁移到Spark平台的项目上遇到了一些平台公式翻译为SparkSQL(on Hive)的需求,而Spark采用亲妈语言Scala进行开发.分析过大概需求过后,拟使用编译原理中的EBNF范式模式,进行基于词法的文法解析.于是拟采用传统的正则词法解析到EBNF文法解析的套路来实现,直到发现了StandardTokenParsers这个Scala基于词法单元的解析器类. 二.平台公式及翻译后的SparkSQL 平台公式的样子如下所示: 1 if(XX1_m001[D003