使用Scheme查找列表中的最小元素

时间:2012-10-10 16:52:53

标签: scheme tail-recursion

(define min
  (lambda (l m c)
    (cond ((null? l) (print m))
          (else ((c (car l))
                 if((< c m) (m c))
                 min((cdr l) m c))))))

我想使用tail-recursive方法来完成它,但它不起作用。我在Scheme非常新,希望你能帮助我。谢谢!

2 个答案:

答案 0 :(得分:2)

这看起来像家庭作业,我会给你一些指示,这样你就可以自己解决。填写空白:

(define (mymin lst minval)
  (cond ((null? lst)        ; If the list is empty
         ???)               ; return the minimum value.
        ((< ??? minval)     ; If current element < minimum value
         (mymin ??? ???))   ; advance recursion, current element is new minimum.
        (else               ; If current element >= minimum value
         (mymin ??? ???)))) ; advance recursion, keep the same minimum.

在上面的代码中,我们实现了一个名为mymin的双参数尾递归过程(不要使用名称min,这是一个内置过程。)第一个参数是要遍历的列表;第二个参数存储到目前为止找到的最小值,当递归结束时,它将保留答案。

这样称呼,注意到第一次调用我们需要在第二个参数中传递一个数字,以至于所有其他数字都变小了:

(mymin '(1 2 3 4 0 5) +inf.0)
> 0

答案 1 :(得分:0)

奥斯卡的版本可以使用,但我有一些风格狡辩(这不是对奥斯卡的挖掘,他们很容易让解决方案变得简单)。如果您按照这些方针进行操作,请查看是否可以进行一些更改。

没有虚假参数

你有3个参数,奥斯卡有2个,但这是一个列表,它接受一个输入 - 一个列表。给出错误的额外种子参数,你就会失败。解决此问题的一种方法是在主函数中重复内部。它可能看起来像这样

(define (mymin lst)
  (let ((minval ???))
    (define (findmin lst testval)
      (cond
        (????)
        (????)
        (????))
    (findmin lst minval)))

你看到它是如何工作的吗?您可以将minval初始化为inf.0,如Oscar所做的那样,或初始化为一个特殊的非数值(有一些好的选择,一个比另一个好)。

如果你真的很聪明,你会发现每次都不需要传递两个值。你可以将一个简单的对象传递给每个递归,而不需要内部函数或任何初始化 - 为什么在你拥有开头所需的所有数据时初始化任何具有无限值的东西?

这里有一个如何看的线索(它的开头很像奥斯卡的版本):

(define (mymin lst)
  (cond
    ((null? lst) ???)
    ((?????) (car lst))
    (else (mymin (??????????????????????? lst)))))

在??? s的最后一行中有一些事情发生;)

但是只有在你有一个工作版本之后才尝试这些改进,除非你不能以任何其他方式使它工作。让它工作,然后改进 - 你学习了两次;)

一路上要考虑的事情......

  • 如果列表中只有一个元素,你会返回什么?
  • 测试列表中是否只有一个元素的最简单方法是什么?
  • 如果列表为空,返回的最合理的内容是什么?