OCaml:Quicksort - Tail Recursion,无限循环?

时间:2017-07-14 14:09:00

标签: ocaml quicksort tail-recursion

当我编译我的代码是好的,但是当我调用并执行函数Quicksort时,程序似乎处于无限循环中。我能做什么 ? 我测试了所有函数,但似乎问题出在tQuicksort函数中。 我是初学者。

let h l =
    match l with
        | [] -> raise (Failure "head")
        | x::xs -> x;;

let t l =
    match l with
        | [] -> raise (Failure "tail")
        | x::xs -> xs;;

let rec trev l r = 
    match l with
        | [] -> r
        | x::xs -> trev xs (x::r);;
let rev l = trev l [];;

let rec tunir l1 l2 r =
    match l1 with
        | [] -> if l2 == [] then
                rev r
            else
                tunir [] (t l2) ((h l2)::r)
        | x1::xs1 -> tunir xs1 l2 (x1::r);;


let unir l1 l2 = tunir l1 l2 [];;

let rec tpart x l l1 l2 = 
    match l with
        | [] -> if l1 == [] then
                ((x::[]), l2)
            else
                (l1, (x::l2))
        | (lx:: lxs) -> if (h l) <= x then
                    tpart x (t l) ((h l)::l1) l2
                else
                    tpart x (t l) l1 ((h l)::l2);;

let part x l = tpart x l [] [];;

let rec tnroelem l n =
    match l with
        | [] -> n
        | x::xs -> tnroelem (t l) (n+1);;

let nroelem l = tnroelem l 0;;

let rec tunirL l r = 
    match l with
        | [] -> rev r
        | lx::lxs -> if lx == [] then tunirL lxs r
                    else tunirL((t lx)::lxs) ((h lx)::r);;

let unirL l = tunirL l [];;

let rec tquicksort lm l lM = 
    match l with
        | [] -> unirL (unir (rev lm) lM)
        | lx::lxs -> let (la, lb) = part (h l) (t l) in
                    if (nroelem la < nroelem lb) then tquicksort ((quicksort la)::lm) lb lM
                    else tquicksort lm la ((quicksort lb)::lM)
and quicksort l = tquicksort [] l [];;

let rec geraListaT n l = 
    if n == 0 then l
    else geraListaT (n-1) (n::l);;
let geraLista n = geraListaT n [];;

let lista : int list = geraLista 9;;

List.iter (fun x->print_int x) (quicksort lista)

1 个答案:

答案 0 :(得分:4)

当您尝试quicksort lm l lM并且l只有一个元素时,您错过了一个案例。在这种情况下,所采取的分支是

    | lx::lxs -> let (la, lb) = part (h l) (t l) in
                    if (nroelem la < nroelem lb)
                    then tquicksort ((quicksort la)::lm) lb lM
                    else tquicksort lm la ((quicksort lb)::lM)

然后,无论if的结果如何,您都会执行递归调用quicksort lm' l' lM',其中l'也只有一个元素。这可以通过在空列表之后添加一个额外的案例来修复:

    | lx::[]  -> unirL (unir (rev (l :: lm)) lM)