我正在尝试使用Scheme创建一个Merge2函数,该函数采用2个有序列表并将它们组合成一个有序列表。例如,(merge2 '(1 3 4) '(2 4 5))
将产生(1 2 3 4 4 5)
以下是我的尝试...我觉得这应该可行,我只需检查每个列表的每个min
的{{1}},然后将此car
附加到递归致电min
。然后我的基本情况是当其中一个列表变空时,它应该只返回另一个要追加的列表。
merge2
输出:
(1 2 4)(2 3 4)(2 4)(2 3 4)(4)(2 3 4)(4)(3 4)(4)(4)()(4) /> TypeError:无法调用未定义的方法'apply'[merge2,merge2,merge2,merge2,merge2,merge2,car,merge2,merge2,merge2,merge2,merge2,merge2,car,merge2,merge2,merge2,merge2,merge2,merge2 ,车]
答案 0 :(得分:4)
解决方案更简单,使用两个列表排序的事实,并从一个元素中选择一个元素并根据哪个元素更大来推进它,直到其中一个列表结束。这就是我的意思:
(define (merge lst1 lst2)
(cond ((null? lst1) lst2)
((null? lst2) lst1)
((>= (car lst1) (car lst2))
(cons (car lst2) (merge lst1 (cdr lst2))))
(else
(cons (car lst1) (merge (cdr lst1) lst2)))))
按预期工作:
(merge '(1 3 4) '(2 4 5))
=> '(1 2 3 4 4 5)
答案 1 :(得分:1)
您可能正在努力解决的部分问题是,作为一种函数式编程语言,Scheme是面向表达式的,而不是命令式的。因此,用Scheme编写的所有都有一个值,甚至是条件表达式。一切都是表达式,并进行评估以产生结果。当您坚持使用纯函数式编程样式(Scheme 鼓励,但不严格执行)时,将对表达式进行求值,以生成可以成为另一个要计算的表达式的一部分的结果。简单地评估表达式,它们不是导致计算机的内存状态以某种方式改变的程序;在函数式编程风格中没有副作用。所以,你应该考虑条件表达式的条件处理。
在命令式编程世界中,我能想到的最接近的对象是C或Java的?:
运算符。你的函数是从一系列条件表达式开始的,但它们就像C或Java中的一系列条件表达式,它们没有分配给任何东西,所以结果被“抛弃了。”
相反,开始考虑这些术语:我们希望将两个列表合并在一起,那么如果其中一个列表为空,将两个列表合并在一起意味着什么?这为合并两个列表的迭代过程形成了一种“基本情况”或终止条件。
另外:如果两个列表都不为空,将两个列表合并在一起意味着什么?如果我们可以根据现有列表(即归纳步骤)以较小的列表表达解决方案,那么我们就可以了解递归过程的样子。
因此,这个归纳步骤的部分解决方案将涉及某种表达式,这种表达式基于检查每个列表的car
,以查看哪个列表应该放在列表的合并头部。依然存在。如果(car a)
小于或等于(car b)
,则(car a)
可以成为(merge2 (cdr a) b)
的第一个元素,对吧?这假设有一种计算(merge (cdr a) b)
的方法,当然!
所以,听起来我们正在谈论一个条件表达式,它将成为一个更大的定义或表达式的一部分,它说明将两个列表合并在一起意味着什么:
(cond ((<= (car a) (car b)) (cons (car a) (merge2 (cdr a) b) ) )
...there's more to write here to finish the conditional expression )
我希望这有助于更清楚地了解奥斯卡·洛佩兹如何得出他的解决方案;你可以看到我上面开始写的条件表达式也在他提出的函数中!
这一切的关键部分是考虑递归过程和递归定义。