我想實現在OCaml的一個尾遞歸列表排序功能,我想出了下面的代碼:尾遞歸歸併排序OCaml中
let tailrec_merge_sort l =
let split l =
let rec _split source left right =
match source with
| [] -> (left, right)
| head :: tail -> _split tail right (head :: left)
in _split l [] []
in
let merge l1 l2 =
let rec _merge l1 l2 result =
match l1, l2 with
| [], [] -> result
| [], h :: t | h :: t, [] -> _merge [] t (h :: result)
| h1 :: t1, h2 :: t2 ->
if h1 < h2 then _merge t1 l2 (h1 :: result)
else _merge l1 t2 (h2 :: result)
in List.rev (_merge l1 l2 [])
in
let rec sort = function
| [] -> []
| [a] -> [a]
| list -> let left, right = split list in merge (sort left) (sort right)
in sort l
;;
但它似乎實際上並不是尾遞歸的,因爲我遇到了「評估期間堆棧溢出(循環遞歸?)」的錯誤。
你能幫我看看這段代碼中的非尾遞歸調用嗎?我搜索了很多,沒有找到它。 Cout它是在sort
函數中的let綁定?
哦,我想我明白了;謝謝!但是,如何讓我的函數遞歸? – 2010-03-27 14:50:28
你能解釋爲什麼延續實際上使函數尾遞歸?或者他們只是將從棧(可能是溢出的)棧中捕獲棧幀的過程移動到生成的閉包? – Dario 2010-03-27 16:09:51
嗯,我想這應該起作用,但我並不真正瞭解k功能的作用。你能解釋一下嗎?非常感謝! 雖然我已經測試過,但它並沒有解決溢出問題......任何想法爲什麼? – 2010-03-27 16:56:33