【问题标题】:How can I convert this recursive solution into an iterative one?如何将此递归解决方案转换为迭代解决方案?
【发布时间】:2014-11-02 04:38:47
【问题描述】:

我在 Lisp 中有以下递归函数

(defun f (item tree)
  (when tree
    (if (equal item (car tree)) tree
      (if (and (listp (car tree))
           (equal item (caar tree)))
      (car tree)
    (if (cdr tree)
        (f item (cdr tree)))))))

这个函数接收一个 tree 和一个 item 来在它的直接叶子中寻找。如果 item 是任何子列表的汽车,那么它将返回该子列表。也就是说,

  • (f 'c '(a b c)) => (c)
  • (f 'b '(a b c)) => (b c)
  • (f 'a '((a 1 2) b c)) => (a 1 2)

我最近被告知 (Emacs Lisp) 不进行尾递归优化,因此有人建议我将其转换为 while 循环。我在 Lisp 中的所有训练都是为了避免这样的循环。 (我坚持认为它们是 un 功能的,但那是迂腐的边缘。)我为更符合风格做了以下尝试:

(defun f (item tree)
  (let ((p tree))
    (while p
      (cond
       ((equal item (car p)) p)
       ((and (listp (car p))
             (equal item (caar p)))
        (car tree))
       (t (f item (cdr p))))
      (setq p (cdr p)))))

为了简洁/清晰,我已经缩短了函数名称,但如果您是 emacs 的高级用户,请查看 where it is being used

【问题讨论】:

  • 除非你的树可以嵌套数百层,否则没有必要避免递归。默认递归限制为 400。
  • 您的重写版本在(t (f item (cdr p)))) 行上递归。
  • @Barmar 我知道while“解决方案”目前是递归的。据我所知,它甚至也不起作用;我还没有测试过——这只是我试图展示的东西,所以这不是一个 gimmeh-teh-codez Q。:)

标签: algorithm lisp elisp


【解决方案1】:

您的“迭代”解决方案仍在递归。它也不会返回在 cond 表达式中找到的值。

以下版本将变量设置为找到的结果。如果找到结果,则循环结束,因此可以返回。

(defun f (item tree)
  (let ((p tree)
        (result nil))
    (while (and p (null result))
      (cond ((equal item (car p)) (setq result p))
            ((and (listp (car p))
                  (equal item (caar p)))
             (setq result (car tree)))
            (t (setq p (cdr p)))))
    result))

【讨论】:

    猜你喜欢
    • 2020-06-07
    • 1970-01-01
    • 2019-06-26
    • 1970-01-01
    • 2016-02-15
    • 1970-01-01
    • 2013-07-22
    • 2014-08-20
    • 1970-01-01
    相关资源
    最近更新 更多