1
(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))))))

我想用尾递归的方法来做,但它不起作用。我是Scheme的新手,希望你能帮助我。谢谢!

4

2 回答 2

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(不要使用 name min,这是一个内置过程。)第一个参数是要遍历的列表;第二个参数存储到目前为止找到的最小值,当递归结束时,它将保存答案。

像这样调用它,注意对于第一次调用,我们需要在第二个参数中传递一个非常大的数字,以至于所有其他数字都更小:

(mymin '(1 2 3 4 0 5) +inf.0)
> 0
于 2012-10-10T17:05:10.497 回答
0

Oscar 的版本会起作用,但我有一些风格上的小问题(这不是对 Oscar 的挖苦,他保持简单以使解决方案更简单)。如果你让它按照这些思路工作,看看你是否可以做一些改变。

无虚假参数

你有 3 个参数,Oscar 有两个,但这是一个接受一个输入的列表 - 一个列表。提供错误的额外种子参数,您将失败。解决此问题的一种方法是在 main 函数中重复出现。它可能看起来像这样

(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的最后一行发生了一些事情;)

但是,只有在您拥有工作版本后才能尝试这些改进,除非您无法以任何其他方式使其工作。让它工作,然后改进——你学了两次;)

一路走来,有些事情要考虑...

  • 如果列表中只有一个元素,你会返回什么?
  • 测试列表中是否只有一个元素的最简单方法是什么?
  • 如果列表为空,最合乎逻辑的返回是什么?
于 2012-10-10T19:24:51.600 回答