You're using .NET List<'T>
which is renamed to ResizeArray<'T> in F# to avoid confusion. If you use functional list, merge
function would look like this:
let merge(xs, ys) =
let rec loop xs ys acc =
match xs, ys with
| [], [] -> List.rev acc (* 1 *)
| [], y::ys' -> loop xs ys' (y::acc) (* 2 *)
| x::xs', [] -> loop xs' ys (x::acc) (* 3 *)
| x::xs', y::_ when x <= y -> loop xs' ys (x::acc) (* 4 *)
| _::_, y::ys' -> loop xs ys' (y::acc) (* 5 *)
loop xs ys []
To explain this function in terms of your imperative version:
- The 4th and 5th patterns are corresponding to the first
while
loop where you compare two current elements and add the smaller one into a resulting list.
- The 2nd and 3rd patterns are similar to your 2nd and 3rd
while
loops.
- The first pattern is the case where
i = cnt1
and j = cnt2
and we should return results. Since a new element is always prepended to the accumulator, we need to reverse it to get a list in the increasing order.
To be precise, your merge
function is just one part of merge-sort algorithm. You need a function to split a list in two halves, call merge-sort on two halves and merge two sorted halves into one. The split
function below is left for you as an exercise.
let rec mergeSort ls =
match ls with
| [] | [_] -> ls
| _ -> let xs, ys = split ls
let xs', ys' = mergeSort xs, mergeSort ys
merge(xs', ys')