看了线性的递归和迭代以及树形递归迭代这部分的内容,感觉对递归和迭代又有了新的理解...所以记录一下,也算对这部分内容的总结吧.
首先书中提到的递归与迭代和我以前想的有点不一样,我感觉书中提到的递归和迭代是站在编译器/解释器的基础上来看的,而我之前是站在语言(类C语言的)的具体实现的角度看的.
理解这个需要先看书中提到的两个概念:
1.递归过程
2.递归的计算过程
可以用书中举出的阶乘的例子来看
实现1:
1 (factorial 6) 2 (* 6 (factorial 5)) 3 (* 6 (* 5 (factorial 4))) 4 (* 6 (* 5 (* 4 (factorial 3)))) 5 ... 6 (* 6 (* 5 (* 4 (* 3 (*2 (factorial 1)))))) ---> 720
实现2:
1 (factorial 6) 2 (fact-iter 1 1 6) 3 (fact-iter 1 2 6) 4 (fact-iter 2 3 6) 5 (fact-iter 6 4 6) 6 (fact-iter 24 5 6) 7 (fact-iter 120 6 6) 8 (fact-iter 720 7 6) ---> 720
实现1就是递归的计算过程, 实现2是迭代的计算过程.区别在于:从编译器的角度看, 实现1的实现需要系统维护以后将要执行操作的轨迹,随着递归深度的加深,所需要保存的信息量线性增长. 而对于实现2, 其状态可以用固定数量的状态变量进行描述.
换句话讲,在实现2中,过程中的任何一个点都提供了关于计算状态的完整描述.
1 c --> 递归计算过程 2 递归过程{ --> 迭代计算过程 3 scheme { 4 --> 递归计算过程
然而这两种实现从语言实现的角度来看(c), 都可以用递归实现, 也就都可以称做是递归过程. 然而c语言编译器这种对于递归的这种解释不论是空间效率和还是时间效率都是不尽人意的(在c语言的实现设计中,对于任何递归的解释都属于递归计算过程即使他们从原理上讲是迭代的),这也是为什么c语言有do...while/for 之类的循环结构的原因(对于scheme则不存在这个设计缺陷 --> scheme解释器采用了尾递归的技巧).