繁体   English   中英

递归在 Haskell 中如何工作? - 示例合并 function

[英]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 = 2y = 4xs = [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]调用它。

在将34进行比较之前,不会将 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM