2014-11-25 47 views
1

我不明白为什么我的功能获得最大数量不想工作。如果我正确地思考这个问题,如果第一个原子比第二个原子小,那么你就调用该函数减去列表中的第一个,否则你会用列表的其余部分构造第一个原子,最大的原子。相关代码:在计划列表中获得最大数量

(define (getlargest a_list) 
    (cond 
    ((null? a_list) '()) 
    ((< (car a_list) (cadr a_list)) (getlargest (cdr a_list))) 
    (else (cons (car a_list) (getlargest(cdr a_list)))))) 

回答

4

您当前的过程在运行时失败。即使它没有,你是比较一个元素与下一个,但不会找到最大值,例如在这样的列表中,它将返回1,这是不正确的:'(10 2 0 1)。还有其他的错误,例如 - 为什么你要建立一个列表作为输出,当答案应该是一个数字?你还必须非常小心的边缘情况下,当列表中剩下一个元素时,你的过程失败。

正确的方法是将假定为最大的一个元素与所有其余元素进行比较,如果我们发现一个元素大于假定的最大值,那么我们找到了一个新的最大值。这就是我的意思是:

(define (getlargest a_list) 
    (if (null? a_list) ; edge case: empty list 
     #f    ; return a special value signaling error 
     (let loop ((a_list (cdr a_list)) ; rest of the list 
       (maxval (car a_list))) ; assumed maximum 
     (cond ((null? a_list) maxval) ; if the list is empty, return max 
       ((> (car a_list) maxval) ; current element > max 
       (loop (cdr a_list) (car a_list))) ; found new max 
       (else      ; otherwise 
       (loop (cdr a_list) maxval)))))) ; keep the same max 

当然,在现实生活中,我们将使用内置max程序为同样的目的:

(apply max a_list) 
+1

而内建的'max'很容易实现SRFI 1的'reduce':'(define(max。 (减少(lambda(ab)(如果(> ab)ab))#f项目))' – 2014-11-25 14:58:27

+0

在哪一个笔记,我想你忘了'应用'在你最后一段的某处...... – 2014-11-25 15:03:15

+1

@ ChrisJester-年轻人懂了! – 2014-11-25 15:06:09

2

有您的代码2级的错误:

1)else子句中,你应该递归调用自己,丢弃第二个元素:

(else (getlargest (cons (car a_list) (cddr a_list)))))) 

2)你缺少只有一个元素,其中cadr将失败

((null? (cdr a_list)) (car a_list)) 

而我个人更喜欢得到#f如果该列表是空的名单的情况。因此,该代码将如下所示

(define (getlargest a_list) 
    (cond 
    ((null? a_list)  
    #f) 
    ((null? (cdr a_list)) 
    (car a_list)) 
    ((< (car a_list) (cadr a_list)) 
    (getlargest (cdr a_list))) 
    (else 
    (getlargest (cons (car a_list) (cddr a_list)))))) 

当然,使用foldl一个解决方案是优选的:

(define (getlargest lst) 
    (foldl (lambda (e r) (if (or (not r) (> e r)) e r)) 
     #f 
     lst)) 

,或者可能稍微更有效的:

(define (getlargest lst) 
    (if (null? lst) 
     #f 
     (foldl (lambda (e r) (if (> e r) e r)) 
      (car lst) 
      (cdr lst)))) 
+0

这两个版本都是正确的,但我宁愿使用第二个版本。第一个传递最大值作为列表中的第一个元素,我宁愿为它添加一个新参数。只是我的两美分;) – 2014-11-25 18:52:18

+0

@ÓscarLópez当然,但OP可能想知道他们的代码中的问题。 – uselpa 2014-11-25 18:56:54

2

没有任何环路,使用递归性:

(define (maximum L) 
    (if (null? (cdr L)) 
     (car L) 
     (if (< (car L) (maximum (cdr L))) 
      (maximum (cdr L)) 
      (car L) 
     ) 
    ) 
) 
0
(define (maxim lst) 
    (vector-argmax (lambda (x) x) (list->vector lst)))