Merge sort for f sharp

后端 未结 2 739
清酒与你
清酒与你 2021-01-14 14:28

This is my code, when I enter a very large number I get stack overflow error does anyone know why? When i enter a very large number i get that error and im not really sure w

2条回答
  •  不思量自难忘°
    2021-01-14 15:09

    In both your functions you had the problem, that the last step you take is not the recursive call but some other thing:

    • in merge it is the :: operation
    • in mergesort it is the merge

    So you have to get to a point where the very last thing is the recursive call!

    One possibility in situations where you have more than one recursive call to make is to use continuations - the idea is to pass a function around that should be called with the result of the current step and then continue the computation from there.

    this is a tail-recursive version of mergesort using this technique:

    let mergesort xs = 
        let rec msort xs cont = 
            match xs with
            | []    -> cont []
            | [x]   -> cont xs
            | _     -> 
                let mid = List.length xs / 2
                let (xs', xs'') = List.splitAt mid xs
                msort xs' (fun ys' -> msort xs'' (fun ys'' -> cont (merge ys' ys'')))
        msort xs id
    

    as you can see the idea is not to hard - instead of first calling both recursive paths it starts with just one half but adds a continuation that basically says:

    once I have the result of mergesort xs' I take the result ys' and continue by mergesorting xs'' and then merge those

    of course the second step is done in just the same way (push the merge into the continuation)

    the very first continuation is usually the identity as you can see in the very last line ;)


    and here is something similar for your merge:

    let merge xs ys = 
        let rec mrg xs ys cont =
            match (xs, ys) with
            | ([], ys) -> cont ys
            | (xs, []) -> cont xs
            | (x::xs', y::ys') ->
                if x < y 
                then mrg xs' ys (fun rs -> cont (x::rs))
                else mrg xs ys' (fun rs -> cont (y::rs))
        mrg xs ys id
    

    those will of course take as much space on the heap (probably more) - but that is usually no problem - your stack should be fine ;)

提交回复
热议问题