Liuw's Thinkpad

想要赢就先学会输,想要成功就先学会失败

递归Process转化为迭代Process

with 3 comments

中文实在不清楚Process和Procedure如何进行区别,所以题目写了英文。

SICP习题1.11

A function f is defined by the rule that f(n) = n if n = 3 and f(n) = f(n-1) + 2f(n-2) + 3f(n-3) if n >= 3. Write a procedure that computes f by means of a recursive process. Write a procedure that computes f by means of an interative process

SICP中已经给了一个例子,把linear recursive转化为iterative。后面一个要求其实是要把tree recursive进行转化。

好吧,递归的很简单。

(define (f n)
  (if (< n 3)
      n
      (+ (f (- n 1)) (* 2 (f (- n 2))) (* 3 (f (- n 3))))))

我比较笨点,迭代的想了好久,写出来个挺锉的。

(define (f n)
  (if (< n 3)
      n
      (f-aux  4 2 1 0 3 n)))

(define (f-aux product a b c count n)
  (if (> count n)
      product
      (f-aux (+ a (* 2 b) (* 3 c))
             (+ a (* 2 b) (* 3 c))
             a
             b
             (+ count 1)
             n)))

这个代码是有冗余的。并不需要专门用一个product去记录结果。写出这样的代码,其实是对“迭代”理解得还不够深刻。改进后的代码是这样的。

(define (f n)
  (if (< n 3)
      n
      (f-aux  4 2 1 2 n)))

(define (f-aux a b c count n)
  (if (> count n)
      c
      (f-aux (+ a (* 2 b) (* 3 c))
             a
             b
             (+ count 1)
             n)))

count并不是必要的,可以直接用n自减到0即可。

ChinaUnix的win_hate也给出了一个版本。我改写了一下,好看点。

(define (g n)
  (g-aux 0 1 2 n))

(define (g-aux x y z n)
  (if (= 0 n)
      x
      (g-aux y z (+ (* 3 x) (* 2 y) z) (- n 1))))

但是这个版本的定义域默认是非负整数,我觉得这是不合适的,因为题目中没有明确指出这一点。

总结一下,有几点比较有意思的:

1. 线性递归和树形递归的尾递归情况,可以转化为迭代,其他情况未考究;
2. 转化时,关键是总结出各个参数的关系,没有必要使用专门的参数去记录结果;
3. 理解迭代的关键点是,每一时刻参数都保持有函数进一步运算的必要信息,而递归把这些信息放在了栈上,由系统隐式操作。

© 2010, liuw. All rights reserved.

Written by liuw

January 26th, 2010 at 11:30 am

3 Responses to '递归Process转化为迭代Process'

Subscribe to comments with RSS or TrackBack to '递归Process转化为迭代Process'.

  1. 这本书翻译的很纠结

      (Quote)

    synzz

    24 Feb 10 at 13:58

  2. @synzz
    一般都看英文了……

      (Quote)

    liuw

    24 Feb 10 at 15:40

  3. 传说中的sicp

      (Quote)

    Lox

    1 Nov 10 at 10:35

Leave a Reply

*