使用递归的最大列表?

时间:2011-08-12 23:31:23

标签: common-lisp

我的任务是在lisp中编写函数,通过使用递归来找到作为函数参数给出的列表的最大值。我尝试但是我有一些错误。我是Lisp的新手,我使用的是cusp插件对于eclipse。这是我的代码:

(defun maximum (l)
  (if (eq((length l) 1)) (car l)  
   (if (> (car l) (max(cdr l)))
    (car l) 
     (max (cdr l))
))

8 个答案:

答案 0 :(得分:16)

如果这不是一个家庭作业问题,你应该喜欢这样的事情:

(defun maximum (list)
  (loop for element in list maximizing element))

甚至:

(defun maximum (list)
  (reduce #'max list))

(两者对于空列表的行为都不同)

如果你真的需要一个递归解决方案,你应该尝试使你的函数更有效,和/或尾递归。看一下Diego's和Vatine的答案,以获得更加惯用和高效的递归实现。

现在,关于你的代码:

在“Lisp方面”这是非常错误的,即使你似乎已经知道如何解决手头的问题。我怀疑你花了很多时间来学习lisp基础知识。搞砸了括号 - 缺少右括号,在((length l) 1)中,您应该注意到评估列表中的第一个元素将用作运算符。此外,你没有真正递归,因为你试图拨打max(而不是maximize)。最后,请勿使用#'eq进行数值比较。此外,如果您以常规方式格式化并缩进代码,您的代码将更具可读性(不仅适用于其他代码)。

你真的应该考虑花一些时间学习一个基本的Lisp教程,因为你的问题清楚地表明,即使是关于Lisp的最基本的东西,比如评估规则也缺乏理解。

答案 1 :(得分:5)

我认为没有真正递归的答案,我只写了一个练习Common-Lisp(目前正在学习)。包含递归版本的先前答案效率低下,因为它递归调用两次maximum。你可以这样写:

(defun my-max (lst)
  (labels ((rec-max (lst actual-max)
             (if (null lst)
                 actual-max
                 (let ((new-max (if (> (car lst) actual-max) (car lst) actual-max)))
                   (rec-max (cdr lst) new-max)))))
    (when lst (rec-max (cdr lst) (car lst)))))

这是(尾)递归和O(n)。

答案 2 :(得分:4)

我认为您的问题在于您引用的是max而不是maximum,这是实际的功能名称。

此代码行为正确:

(defun maximum (l)
  (if (= (length l) 1)
      (car l)
      (if (> (car l) (maximum (cdr l)))
          (car l)
          (maximum (cdr l)))))

答案 3 :(得分:2)

如上所述,该代码意味着一些有趣的低效率(它没有它们,因为您正在调用cl:max而不是递归调用您自己的函数)。

Common Lisp中的函数调用通常不会被记忆,因此如果您在长列表中调用maximum,则最终会以指数运行时结束。

您可以采取一些措施来改善效果。

第一件事是随身携带最大值,递归,依靠让它归还给你。

第二个是永远不要使用成语(= (length list) 1)。这是列表长度中的O(n),但在真实列表的情况下等于(null (cdr list)),后者是O(1)。

第三是使用局部变量。在Common Lisp中,它们通常由let引入。如果你做了类似的事情:

(let ((tail-max (maximum (cdr l))))
   (if (> (car l) tail-max)
     (car l)
     tail-max))

我相信,你会立即从指数变为二次方。如果组合完成(null (cdr l))的事情,你就会掉到O(n)。如果你还在列表中进行了最大可见距离,那么你可能已经下降到O(n)时间和O(1)空间。

答案 4 :(得分:0)

如果我需要在迭代中执行最大代码而不是递归代码将如何? 我先做了一个数组

(do do-array (d l)
          setf b (make-array (length d))
          (do (((i=0)(temp d)) 
               ((> i (- l 1)) (return))
               (setf (aref b i) (car temp))
               (setq i (+ i  1))
               (setq temp (cdr temp))))

答案 5 :(得分:0)

我做了这个,希望它有所帮助,它是递归的。

(defun compara ( n lista)
   (if(endp lista)
       n
       (if(< n (first lista))
          nil
          (compara n (rest lista)))))

(defun max_lista(lista)
    (if (endp lista)
        nil
        (if(compara (first lista) (rest lista))
             (first lista)
             (max_lista(rest lista)))))

答案 6 :(得分:0)

正确的尾递归解决方案

(defun maximum (lst)
    (if (null lst)
        nil
        (maximum-aux (car lst) (cdr lst))))

(defun maximum-aux (m lst)
    (cond
        ((null lst) m)
        ((>= m (car lst)) (maximum-aux m (cdr lst)))
        (t (maximum-aux (car lst) (cdr lst)))))

答案 7 :(得分:0)

https://app-backend.appspot.com/