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

时间:2019-11-21 14:28:07

标签: list haskell recursion

如果我们看一下合并的功能定义

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])

这是我的问题所在:第二个列表的第一个head元素是4,但是由于2 <= 4没有对4进行任何操作,因此4必须仍然在第二个列表中,但是4必须是最后一个元素现在可以将列表与3进行比较。我不知道编译器如何更改第二个列表:最初的4是head元素,但是由于将3与4再次进行比较没有意义,因此必须切换索引。

那么,在第一次比较之后,编译器只是将head元素放在列表的末尾?还是编译器在这里做什么?

2 个答案:

答案 0 :(得分: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函数通常具有前提,它要合并的两个列表已经被分别排序。因此,通常不会使用 MergeSort 之类的算法来调用merge [2,3] [4,1],首先对两个列表进行排序,然后使用merge [2,3] [1,4]来调用它。

答案 1 :(得分:3)

在与3进行比较之前,不会将

1进行比较。 4在单个列表中保留每个值的相对顺序。

递归过程如下:

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混淆,后者将使用 mergeSort作为子例程。

merge

mergeSort [] = [] mergeSort xs = merge (mergeSort first) (mergeSort second) where (first, second) = split xs split xs = ... -- some function to split a list roughly in half 的顺序保持行为使merge成为stable sorting algorithm