理解尾递归向量

时间:2014-05-09 02:01:47

标签: scheme tail-recursion

我有一个尾递归函数,它将一个向量转换为一个列表。我个别理解每一行,但有几个问题:

首先,在代码中代码cons ((vector-ref v i) r) (- i 1)是什么意思? (标记为" Q1"。)我知道它需要向量i的{​​{1}}'并将其与v连接,但为什么必须是i-1?为何不与i-1合作?例如如果向量v长度为5,则元素5与数字4连接。我知道它正在制作向量列表,但为什么要使用i+1(减少)?任何人都可以给我一个解释吗?

i-1

2 个答案:

答案 0 :(得分:1)

明智地使用print语句来理解递归函数的工作原理非常有用。我添加了

      (print r)

正下方

      (lambda (vec r i)

我跑了命令:

(vector->list:rec (vector 1 4 6 8 9 10))

这是输出:

(10)
(9 10)
(8 9 10)
(6 8 9 10)
(4 6 8 9 10)
(1 4 6 8 9 10)
=> (1 4 6 8 9 10)

第一次调用helper时,使用列表调用它,该列表的唯一项是向量的最后一项:

      (cons (vector-ref v (- (vector-length v) 1)) '())

使用

可以简化
      (list (vector-ref v (- (vector-length v) 1)))

回答Q1

该行

            (helper vec (cons (vector-ref v i) r) (- i 1))  ;; Q1

将(向量,cons es)向量的i元素预先添加到包含向量的i+1及以上项的列表中。

在我运行的示例中,当i3时,r(9 10)

如果我理解正确的话,这与你认为这句话所做的相反。

此函数从i的最高有效值递归,并在每次递归调用中递减。这就是(- i 1)作为上述helper调用的最后一个参数的内容。

回答“另外,检查总长度在哪里?”

该行

 (if (> (vector-length v) 0)  ;; line 9

检查输入的总长度是否大于0.只有这样才会遇到调用helper的麻烦。否则,它只返回一个空列表。

希望这有点道理。

答案 1 :(得分:0)

每次调用i减少的原因是i用于确定我们何时到达向量的末尾。我们的想法是,当我们最初调用helper函数时,我们将i设置为向量的长度(减去2),然后在每次递归调用中将i减少1,直到它变得小于0,此时我们知道我们已经完成了整个向量。

我认为,导致您混淆的问题在于您正在正确解析cons来电 - 计算括号表明该来电真的是(cons (vector-ref v i) r) - (- i 1)是只是helper的第三个参数。

最后,在第9行检查向量的长度大于0的想法是,如果向量的长度为0,我们只想返回一个空列表'();如果我们没有进行此检查,那么如果我们输入空向量,那么对(vector-ref v (- (vector-length v) 1))的调用将变为(vector-ref v -1),这显然会失败。我不确定“总长度检查”是什么意思,但(vector-length v)确实返回v的整个长度。