C++抽象编程——递归简介(2)——阶乘函数的执行分析
来源:互联网 发布:cocostudio mac 下载 编辑:程序博客网 时间:2024/06/07 03:53
7.2 Thefactorial function.
单单一个收集筹款的例子,是不足以说明递归的强大的,为了深入理解递归,我们举一个更接近编程的例子。对大多数人来说,刚刚开始学习递归,最好的理解方式就是用简单的含有递归结构的数学函数来理解。而最常见的就是阶乘函数(factorial function)。我们先写个函数的原形
int fact(int n);
意思就是,输入整数n, 我们返回它的阶乘,比如n=5,返回 5*4*3*2*1=120; 当然 我们很容易用for循环来编写这个程序,而在递归的程序中,我们是没有这个for 循环的,但是我们同样实现了这个循环,我们要尝试从不同的方法解决这个问题。
7.2.1The recursive formulation of fact
只要我们认真观察,我们就可以发现,每一个阶乘都可以用更小的个阶乘表示,在数学上可以用下面公式表示
n! = n × (n – 1)!.
因此 4!=4 x 3!,而3!=3x2!.为了这个公式不能永远被分下去,数学上我们定义 0!= 1;所以,完整的数学定义可以写成下面的形式
这个定义就是递归的数学公式的定义。所以我们现在要找递归的基本特征——找到 n-1的阶乘(与原来问题一样的形式)。所以,我们可以通过同样的的定义来找到(n-1)!=(n-1)x(n-2)!。从这里,我们可以看到,严格的数学定义,为递归函数提供了模板(the practical impact of the mathematicaldefinition is that it provides a template for a recursive implementation.), 我们可以很轻松的用C++的编程语言来写出这个程序:
int fact(int n) {int result = 1;for (int i = 1; i <= n; i++) {result *= i;}return result;}
当n=0的时候,就是simple cases,直接返回1;如果不是,那么程序通过计算(n-1)!来得到答案。这个程序就是直接按照阶乘的数学定义来写的,并且 fact 函数都含有同样的递归结构.
7.2.2 Tracing the recursive process
你会惊奇的发现,程序能运行,而且还可以输出正确答案,但是直接看程序,总会觉得程序少了点什么。尽管我们是严格按照数学的定义来写的程序,但是这个递归公式却是很难去区分去理解真正的计算在哪里发生。在上面的程序中,你能发现的就是fact函数再调用fact函数,一直这样下去。似乎有某些魔力促使你的计算机得出正确的答案。所以我们就一起去追踪一下递归的过程。比如我们一开始输入 n = 4
(1) main 函数调用 fact 函数,那么程序就为fact 函数开辟一个框架(frame),类似于栈(stack)。
先判断n=0?,这里n=4,所以执行else 语句
n * fact(n - 1).
(2) 要计算这一行的值,那么就要计算fact(n-1)的值。即
当调用fact(n-1)的时候,重复上面的步骤,n=4,所以n-1=3.
(3) 重复执行(2)步骤
(4)到达边界。这样下去,程序一定会调用到fact(1),此时fact(n-1)=fact(0),此时栈顶为
此时 程序就发生了改变,因为此时 n=0,程序就执行下面的语句
return 1;
(5) 将结果从栈顶返回。也就是执行逆过程,但是这个时候是带着确切的值的
最后一步 4x6=24,结果出来。
- C++抽象编程——递归简介(2)——阶乘函数的执行分析
- C++抽象编程——递归简介(4)——斐波那契函数的分析与扩展
- C++抽象编程——递归简介(1)——递归范式
- C++抽象编程——递归简介(6)——相互递归与递归思想总结
- C++抽象编程——递归简介(3)——The recursive leap of faith
- C语言之函数调用04—递归法求阶乘
- C++抽象编程——递归简介(5)——检查回文数,折半查找
- C/C++程序——递归和循环实现阶乘,并比较N!与(2N N)的大小
- java 阶乘——递归
- python 递归——阶乘
- C#-—体验抽象函数
- C++抽象编程——递归策略(3)——foreach语句的简单实现
- 算法如功夫——C++ 用递归函数计算n的阶乘n!
- 第4周项目5.1—编写递归函数求n的阶乘
- C++扬帆远航——17(递归函数求阶乘)
- C++抽象编程——递归策略(1)——汉诺塔问题(2)
- C++抽象编程——递归策略(3)——生成排列数(2)
- C++抽象编程——递归策略(2)——子集和问题
- L1-003. 个位数统计
- 05:输出保留12位小数的浮点数
- 判断TextView是否有内容省略
- Tensorflow RNN源代码解析笔记1:RNNCell的基本实现
- java字符串转换成时间Unparseable date错误的解决方案
- C++抽象编程——递归简介(2)——阶乘函数的执行分析
- tcp请求建立连接,结束连接握手过程
- Spring源码解读前篇--Spring容器的设计
- 读书笔记 effective c++ Item 25 实现一个不抛出异常的swap
- jstl获取list的长度大小
- Darwin Stream server(DSS服务器)的Relay(中继/转发)设置
- 生成排列 Generating Permutations
- JavaScript函数isFinite()
- 10954