.net 如何使用F实现mergesort#

.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

我需要使用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::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]