如果我们看一下合并的功能定义
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元素放在列表的末尾?还是编译器在这里做什么?
答案 0 :(得分: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
函数通常具有前提,它要合并的两个列表已经被分别排序。因此,通常不会使用 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。