Recursion OCaml中的尾部递归
我试图使用尾部递归在OCaml中实现合并函数,但我面临着尴尬的结果。谁能帮我解决这个问题。提前谢谢Recursion OCaml中的尾部递归,recursion,ocaml,tail-recursion,Recursion,Ocaml,Tail Recursion,我试图使用尾部递归在OCaml中实现合并函数,但我面临着尴尬的结果。谁能帮我解决这个问题。提前谢谢 let rec merge_helper l1 l2 accum = match l1 with [] -> l2@accum | hd::tl -> (match l2 with [] -> l1@accum |x::xs -> merge_helper tl xs l1@l2@accum);; let merge l1 l2 = merge_helpe
let rec merge_helper l1 l2 accum =
match l1 with
[] -> l2@accum
| hd::tl -> (match l2 with
[] -> l1@accum
|x::xs -> merge_helper tl xs l1@l2@accum);;
let merge l1 l2 = merge_helper l1 l2 [];;
merge [1;2;4] [3;4;5];;
- : int list = [4; 5; 2; 4; 4; 5; 1; 2; 4; 3; 4; 5]
首先,您的实现不会在恒定的堆栈空间中运行。
xs@ys
操作不是尾部递归操作,它将进行List.length xs
调用(因此使用这一数量的堆栈帧)。另外,merge
函数通常保留顺序。所以您需要有一个比较函数,它将比较列表中的元素。还不完全清楚,您对merge
函数的期望是什么,以及为什么将结果归类为怪异。对我来说,结果与代码匹配。我觉得很奇怪的是,尽管您正在解构l1
和l2
,但您没有使用解构的结果,而是将整个列表l1
和l2
添加到累加器中
方法如下:从第一个列表中获取一个元素,将该元素添加到累加器中,然后切换列表。因此,该算法的归纳步骤如下:
let rec loop acc xs ys = match xs with
...
| x::xs -> loop (x::acc) ys xs
但是,如果要合并两个保留顺序的已排序列表,则需要在每个步骤中使用两个列表中最小的元素
let merge cmp xs ys =
let rec loop xs ys zs = match xs,ys with
| [],ss|ss,[] -> List.rev_append zs ss
| x :: txs, y :: tys ->
if cmp x y <= 0
then loop txs ys (x::zs)
else loop xs tys (y::zs) in
loop xs ys []
让合并cmp xs ys=
让rec循环xs ys zs=将xs,ys与
|[],ss | ss,[]->List.rev_append zs ss
|x::txs,y::tys->
如果cmpxy首先,您的实现没有在恒定的堆栈空间中运行。xs@ys
操作不是尾部递归操作,它将进行List.length xs
调用(因此使用这一数量的堆栈帧)。另外,merge
函数通常保留顺序。所以您需要有一个比较函数,它将比较列表中的元素。还不完全清楚,您对merge
函数的期望是什么,以及为什么将结果归类为怪异。对我来说,结果与代码匹配。我觉得很奇怪的是,尽管您正在解构l1
和l2
,但您没有使用解构的结果,而是将整个列表l1
和l2
添加到累加器中
方法如下:从第一个列表中获取一个元素,将该元素添加到累加器中,然后切换列表。因此,该算法的归纳步骤如下:
let rec loop acc xs ys = match xs with
...
| x::xs -> loop (x::acc) ys xs
但是,如果要合并两个保留顺序的已排序列表,则需要在每个步骤中使用两个列表中最小的元素
let merge cmp xs ys =
let rec loop xs ys zs = match xs,ys with
| [],ss|ss,[] -> List.rev_append zs ss
| x :: txs, y :: tys ->
if cmp x y <= 0
then loop txs ys (x::zs)
else loop xs tys (y::zs) in
loop xs ys []
让合并cmp xs ys=
让rec循环xs ys zs=将xs,ys与
|[],ss | ss,[]->List.rev_append zs ss
|x::txs,y::tys->
如果cmp x y,你期望得到什么结果?@anthonysecema 1 2 3 4 4 5如果你想合并两个有序列表,那么你至少需要对两个元素进行一次比较。你期望得到什么结果?@anthonysecema 1 2 3 4 4 5如果你想合并两个有序列表,然后你需要至少对两个元素进行一次比较。在合并排序中,你应该先将最小的元素和最大的元素进行合并,如果合并步骤的数量不均匀,则只对最终结果进行一次比较。节省了一些时间和内存。是的,使用更高效的merge\u rev
功能通常很有用。我希望所有列表函数都有一个?rev
参数。在合并排序中,您应该先合并最小值和最大值,如果合并步骤的数量不均匀,则只对最终结果执行一次。节省了一些时间和内存。是的,使用更高效的merge\u rev
功能通常很有用。我希望所有列表函数都有一个?rev
参数。