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(xs1,ys)
				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对两个有序列表进行合并,直到形成一个列表为止。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值