簡體   English   中英

如何使用 F# 實現歸並排序

[英]How to implement mergesort using F#

我需要使用 F# 實現合並排序,為此,我需要 2 個輔助函數:拆分和合並,其中“拆分”將列表拆分為兩個大小相差最多 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)

卡住了,不知道怎么用模式匹配遍歷列表來完成拆分功能。 鑒於拆分和合並是正確的,我也不確定合並排序是否正確。

另外,在我的partern匹配情況下,列表是eigher []ai::af所以我有點不確定,當我們寫ai::af來表示一個列表時,如果列表只包含一個,a1是否等於af元素?

您還可以使用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

這就是一個mergesort實現的樣子:

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)

深思熟慮的准確模式匹配是它的核心。

主要部分mergesort遞歸地應用長度大於 1 的列表的拆分,然后合並由自應用排序的拆分的一半:

  • 對於空參數或單例,它只是將其作為結果回顯
  • 否則(模式匹配的最后一種情況)它使用split將參數list減半為“halve”列表(l1,l2)的元組,然后使用merge將自我應用的結果mergel1l2

split使用輔助函數aux將任何列表轉換為由長度相差不超過 1 的相同元素組成的列表元組。

最后, merge (上面以簡單的方式實現,但顯然不是尾遞歸的方式)將執行排序本身的一對列表重新組裝在一起。 它在內部使用將參數組合成一個元組來將參數模式匹配簡化為 3 種情況: non-empty,emptyempty,non-emptynon-empty,non-empty

merge尾遞歸並不太難,出於教學原因我沒有這樣做。 你可以在這個 gist 中找到尾遞歸版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM