[英]How does recursion work in Haskell? - Example merge function
如果我们看一下合并的函数定义
merge (x:xs) (y:ys) | x <= y = x:merge xs (y:ys)
| otherwise = y:merge (x:xs) ys
输入 [2,3] [4,1]
第一步看起来像这样
2<=4 => 2:merge [3] (1:[4])
我的问题在于:第二个列表的第一个头元素是 4,但是由于 2<=4 没有对 4 做任何事情,所以 4 必须仍在第二个列表中,但 4 现在必须是列表中的最后一个元素所以可以将 3 与 1 进行比较。我想知道编译器如何更改第二个列表:起初 4 是 head 元素,但由于再次将 3 与 4 进行比较没有意义,因此必须切换索引。
那么编译器只是在第一次比较之后将头元素放在列表的末尾吗? 或者编译器在这里做什么?
我想知道编译器如何更改第二个列表。
它不是。 如果我们调用merge [2,3] [4,1]
那么您描述的子句将触发,其中: x = 2
, y = 4
, xs = [3]
和ys = [1]
。 它确实会检查2 <= 4
是否成立,然后调用合并:
x : merge xs (y:ys)
所以这意味着如果我们使用刚刚分配的变量,我们会得到:
2 : merge [3] (4:[1])
或更简洁:
2 : merge [3] [4,1]
我想知道编译器如何更改第二个列表:起初 4 是 head 元素,但由于再次比较 3 和 4 没有意义,因此必须切换索引。
这种merge
function 通常有一个前提条件,即它旨在合并的两个列表已经单独排序。 所以通常不会用MergeSort之类的算法调用merge [2,3] [4,1]
,首先对两个列表进行排序,然后再使用merge [2,3] [1,4]
调用它。
在将3
与4
进行比较之前,不会将 3 与1
进行比较; merge
保留单个列表中每个值的相对顺序。
递归进行如下:
merge [2,3] [4,1] == 2 : merge [3] [4,1] -- 2 < 4
== 2 : 3 : merge [] [4, 1] -- 3 < 4
== 2 : 3 : [4, 1] -- assuming merge [] ys == ys
不要将merge
与使用merge
作为子例程的mergeSort
混淆。
mergeSort [] = []
mergeSort xs = merge (mergeSort first) (mergeSort second)
where (first, second) = split xs
split xs = ... -- some function to split a list roughly in half
mergeSort
merge
成为一种稳定的排序算法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.