SICP 关于递归迭代的重新理解以及尾递归的引入...

看了线性的递归和迭代以及树形递归迭代这部分的内容,感觉对递归和迭代又有了新的理解...所以记录一下,也算对这部分内容的总结吧.

首先书中提到的递归与迭代和我以前想的有点不一样,我感觉书中提到的递归和迭代是站在编译器/解释器的基础上来看的,而我之前是站在语言(类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解释器采用了尾递归的技巧).

时间: 2024-10-17 07:24:26

SICP 关于递归迭代的重新理解以及尾递归的引入...的相关文章

编程算法 - 中序遍历 递归/迭代 代码(C)

中序遍历 递归/迭代 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 中序遍历(InOrder)作为二叉搜索树的排序方式, 有着重要的作用. 递归和迭代的方法都需要掌握, 迭代主要使用了栈(stack)进行输入输出. 代码: /* * main.cpp * * Created on: 2014.9.18 * Author: Spike */ /*eclipse cdt, gcc 4.8.1*/ #include <iostream> #inclu

二叉树基本操作续二:前序、中序、后序遍历(非递归 迭代方式)

这里给出二叉树三种遍历方式的迭代实现代码.二叉树的递归实现使用系统栈入栈出栈,而非递归的迭代实现方法就是手动维护一个栈,来模拟递归的入栈出栈过程. 本文没有给出用户栈的代码,如果需要结合上篇的测试代码一起测试,则需要自己实现自己的栈,以及基本的pop.push等栈操作函数. 前序迭代遍历: 1 void iter_preorder(tree_pointer ptr) 2 { 3 //前序遍历:先遍历根节点,然后再分别遍历左右子树 4 int top = -1; 5 tree_pointer st

高维空间中的体积(包含递归思想的初步理解)

n维超球体的体积的变化的特点:当n<=7的时候,体积是增大的:当n>7的时候,体积是缩小的,可以小到0 因此可以从中推出,如果以固定的半径进行取样,这取到的样本的数量是先增大,然后再缩小的. 递归思想的通俗理解:你打开面前这扇门,看到屋里面还有一扇门.你走过去,发现手中的钥匙还可以打开它,你推开门,发现里面还有一扇门,你继续打开它.若干次之后,你打开面前的门后,发现只有一间屋子,没有门了.然后,你开始原路返回,每走回一间屋子,你数一次,走到入口的时候,你可以回答出你到底用这你把钥匙打开了几扇门

&lt;13&gt;【了解】计算机中的进制+【理解】原码反码补码基本概念+【理解】为什么要引入反码、补码?+【掌握】位运算符介绍及使用+位运算应用:编程实现10进制转2进制

1 #include <stdio.h> 2 3 int main(int argc, const char * argv[]) { 4 5 //定义10进制数,打印出10.8.16进制的值 6 int a = 13; 7 printf("%d\n",a); 8 printf("%o\n",a); 9 printf("%x\n",a); 10 11 //int 64 4个字节 12 int b = 0b0000000000000000

SICP:1.37 递归/迭代求无穷连分式

#lang racket (define (cont-frac N D k) (define (cf t) (if (= t 1) (/ (N t) (D t)) (/ (N t) (+ (D t) (cf (- t 1)))) );if );cf (cf k) );cont-frac (define (cont-frac-iteration N D k) (define (cf result t) (if (= t k) result (cf (/ (N t) (+ (D t) result)

javase_递归&amp;迭代

一.递归  程序调用自身的编程技巧称为递归( recursion).递归做为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量.递归的能力在于用有限的语句来定义对象的无限集合.  递归的三个条件: 边界条件 递归前进段 递归返回段 当边界条件不满足时,递归前进:当边界条件满足时,递归返回.

对于&quot;单链表逆置和递归&quot;的问题的理解.

一. 相关知识要点: 学习或了解基础数据结构和C语言, 对基础链表知识或相关知识有概况性认识. 例如: 本题目结构为: 1 #define elem_type int 2 3 typedef struct _single_list { 4 elem_type data; //所存的数据元素 5 _single_list *next; //所存的指针元素 6 }ListNode; 二. 问题的思考过程(本题以3种不同的方法解决): <1>类似于我们学习的C语言基础知识中的冒泡排序(参考C程序设计

尾递归=递归+迭代?

0 引言 平时见惯了递归和迭代,递归直观,但太占内存和时间,迭代运算快,但是不如递归代码简洁明了.那么可不可以把这两种算法的优点糅合在一起?答案是肯定的,尾递归就提供了这样一种机制. 1 尾递归是什么 简单地说,尾递归就是披着“递归”的外衣,却拥有一颗“迭代”的心.外观上看起来像递归,但内部进行了迭代的运算.下面举例说明. 2 阶乘示例 2.1 先看阶乘的迭代算法: 2.2 再看阶乘的递归算法: 2.3 最后看阶乘的尾递归算法: 3 斐波那契数列示例 3.1 先看斐波那契数列的迭代算法: 3.2

LeetCode145 Binary Tree Postorder Traversal Java题解(递归 迭代)

题目: Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary tree {1,#,2,3}, 1 2 / 3 return [3,2,1]. 解题: 递归的还是和前面中序和先序一样,只是交换一下顺序而已 public static List<Integer> result=new ArrayList<Integer>(); public