.net 如何使用F实现mergesort#
我需要使用F#实现合并排序,为此,我需要两个辅助函数:split和merge,其中“split”将一个列表拆分为两个较小的列表,其大小最多相差1。我正在尝试创建拆分函数。以下是我迄今为止实现的合并和拆分功能:.net 如何使用F实现mergesort#,.net,algorithm,sorting,f#,mergesort,.net,Algorithm,Sorting,F#,Mergesort,我需要使用F#实现合并排序,为此,我需要两个辅助函数:split和merge,其中“split”将一个列表拆分为两个较小的列表,其大小最多相差1。我正在尝试创建拆分函数。以下是我迄今为止实现的合并和拆分功能: let rec merge (l: 'a list, m: 'a list)= match l,m with |[],[] -> [] |[],mi::mf -> mi::mf |li::lf,[] -> li::lf |li::l
let rec merge (l: 'a list, m: 'a list)=
match l,m with
|[],[] -> []
|[],mi::mf -> mi::mf
|li::lf,[] -> li::lf
|li::lf, mi::mf -> if li<mi then li::merge (lf,mi::mf)
else mi::merge(li::lf,mf)
let split (l: 'a list)=
let n= l.Length
if n%2=1 then
for i in 1..n/2 do
let rec mergesort (l :'a list)=
let (left,right)=split l
if left.Length>1 || right.Length>1 then
merge(mergesort left,mergesort right)
else
merge(left,right)
让rec合并(l:'a列表,m:'a列表)=
把我,我和
|[],[] -> []
|[],mi::mf->mi::mf
|li::lf,[]->li::lf
|li::lf,mi::mf->如果li1 | |对。那么长度>1
合并(左合并排序,右合并排序)
其他的
合并(左、右)
我被卡住了,我不知道如何使用模式匹配遍历列表来完成拆分功能。考虑到拆分和合并是正确的,我也不确定mergesort是否正确
此外,在我的partern匹配案例中,列表是八个
[]
或ai::af
,因此我有点不确定,当我们编写ai::af
来表示列表时,如果列表只包含一个元素,a1是否等于af?这就是简单的合并排序
实现可能看起来的样子:
let split list =
let rec aux l acc1 acc2 =
match l with
| [] -> (acc1,acc2)
| [x] -> (x::acc1,acc2)
| x::y::tail ->
aux tail (x::acc1) (y::acc2)
in aux list [] []
let rec merge l1 l2 = // this version is NOT tail-recursive
match (l1,l2) with
| (x,[]) -> x
| ([],y) -> y
| (x::tx,y::ty) ->
if x <= y then x::merge tx l2
else y::merge l1 ty
let rec mergesort list =
match list with
| [] -> []
| [x] -> [x]
| _ -> let (l1,l2) = split list
in merge (mergesort l1) (mergesort l2)
let split list=
让rec aux l acc1 acc2=
匹配
|[]->(acc1、acc2)
|[x]->(x::acc1,acc2)
|x::y::tail->
辅助尾翼(x::acc1)(y::acc2)
在辅助列表中[][]
让rec merge l1 l2=//此版本不是尾部递归
将(l1,l2)与
|(x,[])->x
|([],y)->y
|(x::tx,y::ty)->
如果x[]
|[x]->[x]
|->let(l1,l2)=拆分列表
合并中(合并排序l1)(合并排序l2)
经过深思熟虑的精确模式匹配是其核心
主要部分mergesort
递归地应用长度大于1的列表的拆分,然后合并被拆分的部分,这些部分通过自身应用进行排序:
- 对于一个空参数,或者一个单例,它只是作为结果重复它
- 否则(模式匹配的最后一种情况)它使用
将参数split
减半为一个“一半”列表的元组list
,然后使用(l1,l2)
将自我应用的结果合并到merge
和l1
l2
split
使用辅助功能aux
,该功能将任何列表转换为由长度相差不超过1的相同元素组成的列表元组
最后,merge
(上面以简单但显然不是尾部递归的方式实现)将执行排序本身的一对列表重新组装在一起。它在内部将参数组合到元组中,以将参数模式匹配简化为3种情况:非空、空
、空、非空
、和非空、非空
使
merge
tail递归并不太困难,我没有这样做是出于教学上的原因。您可以在中找到尾部递归版本。您也可以使用List.splitInto
而不是实现您自己的拆分功能
let rec mergeSort lst =
let rec merge = function
| l, [] -> l
| [], l -> l
| x::xs, y::ys -> if x < y
then x :: merge (xs, y::ys)
else y :: merge (x::xs, ys)
match List.splitInto 2 lst with
| [l1;l2] -> merge (mergeSort l1, mergeSort l2)
| l -> List.concat l
让rec合并排序lst=
让rec merge=函数
|l,[]->l
|[],l->l
|x::xs,y::ys->if x合并(合并排序l1,合并排序l2)
|l->List.concat l
对不起,x::y::tail是否表示x和y是列表中的前两个元素?@mathnoob:当然,1::2::[]
是[1;2]