C语言函数递归[1]
c语言递归实现1到n的和

C语言递归实现1到n的和简介递归是一种常用的编程技巧,它通过函数自身的调用来解决问题。
在C语言中,递归可以用于实现各种算法和数据结构。
本文将介绍如何使用递归来计算1到n的和,通过详细的代码解释和示例演示,帮助读者理解递归的原理和使用方法。
递归的基本原理递归是一种通过函数自身的调用来解决问题的方法。
在递归中,函数会不断地调用自身,直到满足某个终止条件才停止调用。
递归可以分为两个阶段:递归调用和递归返回。
递归调用是指函数在执行过程中,自己调用自己。
在每次递归调用时,函数会使用不同的参数值,以便在每次调用中解决不同的子问题。
递归调用将问题分解为更小的子问题,直到达到终止条件。
递归返回是指函数在满足终止条件后,通过返回值将结果传递给上一层调用。
通过不断返回结果,最终得到整个问题的解。
递归实现1到n的和下面是使用递归实现1到n的和的C语言代码:#include <stdio.h>int sum(int n) {if (n == 1) {return 1;} else {return n + sum(n - 1);}}int main() {int n;printf("请输入一个正整数n:");scanf("%d", &n);printf("1到%d的和为:%d\n", n, sum(n));return 0;}在上面的代码中,我们定义了一个名为sum的递归函数,它接受一个整数参数n,并返回1到n的和。
在函数内部,我们使用了一个if-else语句来判断是否满足终止条件。
当n等于1时,递归终止,直接返回1。
否则,递归调用sum函数,并将n减1作为参数传入,然后将递归调用的结果与n相加返回。
在main函数中,我们首先从用户输入获取一个正整数n,然后调用sum函数计算1到n的和,并将结果打印出来。
递归的执行过程为了更好地理解递归的执行过程,我们以计算1到5的和为例,来逐步分析递归的调用和返回过程。
c语言编写函数,使用递归的方法求1+2+3+……+n的值

c语言编写函数,使用递归的方法求1+2+3+……+n的值以下是使用递归方法求解1 + 2 + 3 + ... + n的C语言函数:```c#include <stdio.h>// 递归函数int sumUpToN(int n) {// 基本情况:当n 等于0 时,返回0if (n == 0) {return 0;}// 递归情况:返回n 加上前n-1 项的和else {return n + sumUpToN(n - 1);}}int main() {int n;// 获取用户输入printf("Enter a positive integer n: ");scanf("%d", &n);// 检查输入是否为正整数if (n < 1) {printf("Please enter a positive integer.\n");} else {// 调用递归函数并输出结果int result = sumUpToN(n);printf("Sum of 1 to %d is: %d\n", n, result);}return 0;}```这个程序包含一个递归函数`sumUpToN`,该函数接受一个正整数`n` 作为参数,计算1 + 2 + 3 + ... + n的和。
递归函数的基本情况是当`n` 等于0 时返回0,递归情况是返回`n` 加上前`n-1` 项的和。
在`main` 函数中,用户输入一个正整数`n`,然后调用递归函数并输出结果。
程序会检查输入是否为正整数,并在必要时提供错误消息。
《c语言递归算法》课件

C语言递归算法是一种强大的编程技巧,通过函数自身调用实现问题的解决。 本课件将介绍递归算法的概念、实现方式、应用场景、优缺点以及与循环的 区别,同时还会通过案例演示帮助理解。
什么是递归算法?
基本概念
递归是指函数直接或间接地调用自身的过程。
递归特点
递归算法需要有基准条件和递推关系,用于结 束递归和推进递归过程。
递归算法的实现方式
递归函数
通过函数自身调用实现递归,需要定义递归函数和 递归终止条件。
递归流程图
通过流程图展示递归算法的执行过程,帮助理解递 归逻辑。
递归算法的应用场景
1 数学计算
递归算法可以用于解决数学问题,如斐波那契数列、阶乘等。
2 数据结构
递归算法在树、图等数据结构的遍历和搜索中有广泛应用。
递归算法的优点和缺点
优点
• 简化问题复杂度 • 代码结构清晰
缺点
• 执行效率较低 • 内存占用较高
递归算法与循环的区别
1
循环
2
迭代操作
3
递归
函数自身调用
区别
递归更直观,但消耗资源较多;循环更 高效,但代码可读性差。
递归算法的注意事项
1 递归终止条件
保证递归过程能够结束,否则可能导致死循 环。
2 堆栈溢出
过深的递归调用可能导致堆栈溢出,需要注 意递归深度。
递归算法的案例演示
斐波那契数列
通过递归实现斐波那契数列的计算。
二叉树遍历
通过递归遍历二叉树的各种方式。
C语言中递归函数的教学方法

C语言中递归函数的教学方法在教授C语言中的递归函数时,我们可以采用以下教学方法:一、引入递归概念和原理首先,我们需要向学生们解释什么是递归以及递归函数的原理。
递归是指一个函数直接或间接地调用自己的过程。
通过一个简单的例子,如计算阶乘,来引导学生理解递归的概念。
然后,解释递归函数的工作原理,即每一次递归调用都会将问题分解为规模更小的子问题,直到达到基本情况(递归停止条件),然后依次返回结果。
二、示范递归调用过程接着,我们可以使用一个实际的例子来示范递归调用的过程,如计算斐波那契数列。
我们可以用具体的数值来展示函数调用栈,以及每次递归调用会如何返回结果。
这样可以帮助学生更直观地理解递归的工作过程。
三、教授递归函数的编写与调用经过前两步的引导,学生们应该可以理解递归函数的原理。
然后,我们可以教授学生如何编写和调用递归函数。
这包括函数的定义、终止条件的判断和处理、递归调用的方法等。
我们可以使用一些简单的示例,如计算阶乘、斐波那契数列、二叉树的遍历等,来让学生们亲自编写递归函数并运行。
同时,我们需要向学生们强调递归函数的设计的重要性,以避免无限递归导致的程序崩溃。
四、递归函数中的陷阱与优化递归函数在编写过程中可能会遇到一些陷阱,例如无限递归、堆栈溢出等问题。
我们需要向学生们提示这些陷阱,并讲解如何避免或解决这些问题。
此外,我们还可以介绍一些递归函数的优化技巧,例如尾递归优化、缓存中间结果、剪枝等,以提高递归函数的效率和性能。
五、扩展应用与实际案例最后,我们可以引导学生们探索更多的递归应用和实际案例。
例如,图的深度优先、回溯法、分治算法等都是基于递归的常见算法。
我们可以通过这些实际案例来巩固学生们对递归函数的理解和运用能力。
同时,我们也可以鼓励学生们尝试自己设计和实现基于递归的算法,以提升他们的创造力和解决问题的能力。
六、练习和总结在教学结束时,我们可以给学生们一些练习题来巩固他们对递归函数的理解和编写能力。
c语言函数自我调用

c语言函数自我调用C语言函数自我调用自我调用是指函数在执行过程中调用自身的行为。
在C语言中,函数自我调用是一种常见的编程技巧,可以用来解决一些需要重复执行的问题,如递归算法等。
本文将详细介绍C语言函数自我调用的原理、应用场景以及注意事项。
一、函数自我调用的原理函数自我调用的原理是通过在函数体内部使用函数名来调用函数本身。
当函数被调用时,会创建一个新的函数执行上下文,并将参数传递给新的函数。
在函数内部,可以通过条件判断语句来决定是否继续调用函数自身,从而实现重复执行的效果。
二、函数自我调用的应用场景1. 递归算法:递归是指函数调用自身的过程。
递归算法常用于解决具有递归结构的问题,如求解阶乘、斐波那契数列等。
通过函数自我调用,可以简化递归算法的实现,使代码更加简洁和可读。
例如,以下是一个计算阶乘的递归函数:```cint factorial(int n) {if (n == 0 || n == 1) {return 1;} else {return n * factorial(n - 1);}}```2. 链表操作:链表是一种常见的数据结构,通过指针将一组节点按顺序连接起来。
在对链表进行操作时,函数自我调用可以用来遍历链表、查找节点等。
例如,以下是一个递归函数,用于计算链表的长度:```cint getLength(Node* head) {if (head == NULL) {return 0;} else {return 1 + getLength(head->next);}}```3. 树的遍历:树是一种重要的数据结构,常用于表示层次结构的数据。
在对树进行遍历时,函数自我调用可以用来实现先序遍历、中序遍历、后序遍历等。
例如,以下是一个递归函数,用于实现树的先序遍历:```cvoid preOrderTraversal(TreeNode* root) {if (root != NULL) {printf("%d ", root->value);preOrderTraversal(root->left);preOrderTraversal(root->right);}}```三、函数自我调用的注意事项1. 递归终止条件:递归函数必须包含一个终止条件,否则会导致无限递归,最终导致栈溢出。
C语言三种方法求阶乘

C语言三种方法求阶乘求阶乘是一道经典的数学问题,在C语言中有多种方法可以计算阶乘。
本文将介绍三种常用的方法:递归、循环和动态规划。
一、递归法递归法是一种自己调用自己的方法。
对于阶乘问题,可以将阶乘定义为n的阶乘等于n乘以(n-1)的阶乘。
递归函数的基本思路就是将问题不断分解为规模更小的子问题,直到子问题无法再分解为止。
```c#include <stdio.h>unsigned long long factorial(unsigned int n)if(n == 0 , n == 1)return 1;elsereturn n * factorial(n-1);int mainunsigned int n;printf("请输入一个非负整数:");scanf("%u", &n);printf("%u的阶乘是%llu\n", n, factorial(n));return 0;```二、循环法循环法是一种通过循环迭代来解决问题的方法。
对于阶乘问题,可以用一个循环从1到n依次相乘。
```c#include <stdio.h>unsigned long long factorial(unsigned int n)unsigned long long result = 1;for(int i = 1; i <= n; i++)result *= i;}return result;int mainunsigned int n;printf("请输入一个非负整数:");scanf("%u", &n);printf("%u的阶乘是%llu\n", n, factorial(n));return 0;```三、动态规划动态规划是一种将问题分解为更小的子问题,并保存子问题的解以供后续使用的方法。
自考c语言程序设计试题及答案
自考c语言程序设计试题及答案一、选择题(每题2分,共20分)1. C语言中,用于定义变量的关键字是:A. varB. intC. letD. define答案:B2. 下列哪个选项不是C语言中的合法标识符?A. _nameB. 2nameC. nameD. name2答案:B3. C语言中,用于表示逻辑“与”操作的运算符是:A. &&B. ||C. !D. ~答案:A4. 下列哪个选项不是C语言中的控制语句?A. ifB. switchC. forD. goto答案:B5. 在C语言中,用于定义一个结构体的关键字是:A. structB. unionC. enumD. typedef答案:A6. C语言中,用于实现函数递归调用的关键字是:A. returnB. callC. recursiveD. self答案:A7. C语言中,用于定义一个指针变量的关键字是:A. pointerB. ptrC. *D. ref答案:C8. 下列哪个选项是C语言中的合法数组声明?A. int arr[10];B. int arr[];C. int arr[10] = {1, 2, 3};D. All of the above答案:D9. C语言中,用于定义一个枚举类型的关键字是:A. enumB. enum typeC. typeD. typedef答案:A10. 在C语言中,用于实现文件操作的库函数位于哪个头文件中?A. stdio.hB. stdlib.hC. string.hD. math.h答案:A二、填空题(每题3分,共30分)1. 在C语言中,定义一个整型变量并初始化为10的语句是:`int a = ______;`答案:102. C语言中,用于计算两个整数相加的表达式是:`________ + b;`答案:a3. C语言中,用于定义一个浮点型数组的语句是:`float arr[5] = {1.1, 2.2, 3.3,4.4, ______};`答案:5.54. 在C语言中,用于定义一个函数的关键字是:`________ void myFunction();`答案:void5. C语言中,用于定义一个指针指向整型变量的语句是:`int *p = ______;`答案:&a6. C语言中,用于定义一个结构体的语句是:`struct Student {int id; char name[50];};`答案:(无需填空)7. C语言中,用于定义一个枚举类型的语句是:`enum Color {RED, GREEN, BLUE} color;`答案:(无需填空)8. 在C语言中,用于定义一个二维数组的语句是:`int arr[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, ______ };`答案:{8, 9, 10, 11}9. C语言中,用于实现文件读取的函数是:`________`答案:fopen10. C语言中,用于实现字符串连接的函数是:`________`答案:strcat三、简答题(每题5分,共20分)1. 简述C语言中函数的定义和调用过程。
c语言程序设计试题及答案
c语言程序设计试题及答案C语言程序设计试题及答案一、选择题(每题2分,共20分)1. C语言中,以下哪个是合法的变量名?A. 2variableB. variable-nameC. variable_nameD. variable-2答案:C2. 以下哪个语句不是C语言中的输入语句?A. scanf("%d", &x);B. printf("%d", x);C. gets("string");D. getchar();答案:B3. C语言中,以下哪个不是标准库函数?A. printf()B. malloc()C. strcpy()D. main()答案:D4. 以下哪个选项是C语言中正确的数组声明?A. int array[];B. int [10] array;C. int array[10];D. int [10] = array;答案:C5. 以下哪个是C语言中正确的字符串字面量?A. "Hello World"B. 'Hello World'C. "Hello\nWorld"D. "Hello World"答案:C6. C语言中,以下哪个是正确的函数声明?A. int function();B. void myFunction(int x, int y);C. int myFunction(int x, int y) {}D. int myFunction(int x, int y) { return x + y; }答案:B7. 在C语言中,以下哪个是正确的条件语句?A. if (x = 5)B. if (x == 5)C. if (x = 5) { x++; }D. if (x == 5) { x++; }答案:D8. 在C语言中,以下哪个是正确的循环语句?A. for (int i = 0; i <= 10; i++) {}B. for (int i = 0; i < 10; i--) {}C. while (x != 0) { x--; }D. do { x++; } while (x != 0);答案:D9. 在C语言中,以下哪个是正确的指针声明?A. int *ptr;B. *int ptr;C. int ptr*;D. int * ptr;答案:A10. C语言中,以下哪个不是运算符?A. +B. -C. :D. *答案:C二、简答题(每题5分,共30分)1. 请简述C语言中数组和指针的区别。
c语言函数的嵌套和递归调用方法的实验小结
C语言函数的嵌套和递归调用方法的实验小结一、引言在C语言程序设计中,函数的嵌套和递归调用是两种常用的方法,它们在解决问题和实现特定功能时具有重要作用。
本文将结合实验结果,对C语言函数的嵌套和递归调用方法进行总结和分析,旨在加深对这两种方法的理解和应用。
二、函数的嵌套1. 概念与特点函数的嵌套是指在一个函数内部调用另一个函数。
当函数A中调用了函数B,函数B又调用了函数C,函数C又调用了函数D时,就形成了函数的嵌套调用。
函数的嵌套具有以下特点:(1)提高了程序的模块化和可读性,减少了代码的复杂度。
(2)可以在不同的函数之间传递参数,实现更灵活的功能组合。
(3)需要注意函数的声明顺序和作用域,避免出现未声明的函数引用错误。
2. 实验验证为了验证函数的嵌套调用,在实验中我们设计了一个简单的例子:编写两个函数,分别实现计算阶乘和计算组合数的功能,然后在主函数中进行嵌套调用,计算组合数的值。
实验结果表明,函数的嵌套调用可以实现相互依赖的功能模块,在程序设计中具有一定的灵活性和适用性。
三、递归调用1. 概念与特点递归调用是指一个函数在执行过程中调用了自身,从而形成了一种函数调用的循环结构。
通过递归调用,可以使函数不断重复执行,直到满足特定的条件才停止。
递归调用具有以下特点:(1)简化了程序的结构,使代码更加清晰和易于理解。
(2)能够处理一些需要多级嵌套的问题,极大地提高了代码的复用性和灵活性。
(3)需要设置递归调用的终止条件,避免形成无限循环,导致程序崩溃。
2. 实验验证为了验证递归调用的功能和特点,我们设计了一个典型的递归程序:计算斐波那契数列的前n项值。
实验结果表明,递归调用在实现该问题时具有简洁、高效的特点,使得代码易于阅读和理解,优雅地解决了该问题。
四、两种方法的比较1. 灵活性与适用性函数的嵌套调用主要适用于需要实现不同功能模块之间的交互和依赖关系的情况,具有较强的灵活性和可扩展性。
递归调用主要适用于解决问题具有明显的递归结构或需要多级嵌套的情况,具有较好的适用性和简洁性。
C语言递归函数的执行与求解
时,系统会把调用者 的所 有实 在参数 ,被调用 者的形式参数、局部变量 ,以及调用 者的返回 地址等信息全部压入 “ 递 归工作栈 ”暂存,当
 ̄t U l I l1 ;
1递归函数
( 1 )可 以通过递归调用来缩小问题规模 , 且新 问题 与原 问题有着相 同的形式,只是所 处
C语 言 的特 点之 一就 在于 允许 函数 的递 理 的对 象具有 一定的规 律性 。也就 是说解 决问
< <上 接 2 6 3页
一 ~ . 掰 ~ 一 ~ 一 一 ~ 一 ~ 一 一 ~ 7 一 ~ 一 ~
I n t
3 0
No
用户编号
确保 用人 单位 岗位 需求 发布 的及 时性和 可靠 性。由此 ,本文提 出的高校学生求职招聘系 统
[ 2 2 ] 甘 文 丽 ,王 岚 .基 于轻 量 级 J a v a E E框 架 的 高校 招投 标管 理 系统 [ J ] .实验 室研 究 与探 索 , 2 0 1 2 , l 1 : 1 8 2 - 1 8 5 + 2 1 3 .
题的方法 相同,调 用函数的参 数有规律 的递增
或递减。 ( 2 )递归函数必须有一个终止处理条件, 即必须有一个明确的结束条件,必须在适当 的 时候能够结束递归调用 ,否则会使程序陷入死 循环,导致系统崩溃。 ( 3 )有些使 用递归算法 求解 的问题也可 使用普通循环算法来实现 ,相较于循环程序 ,
2 6 4 ・电子技 术 与软 件工 程
E l e c t r o n i c T e c h n o l o g y &S o f t w a r e E n g i n e e r i n g
P r o g r a m D e s i g n・ 程序设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
递归,作为C语言最经典的算法之一,是一种非常有用的程序设计方法。
虽然用递归算法编写的程序结构清晰,具有很好的可读性,还往往使某些看起来不易解决的问题变得容易解决。
但在递归函数中,由于存在着自调用过程,程序控制反复进入其自身,使程序的分析设计有一定困难,致使很多初学者往往对递归迷惑不解,也在这上面花了不少的时间,却收效甚微。
那么,究竟什么是递归?怎么实现递归呢?
所谓递归,简而言之就是在调用一个函数的过程中又直接或间接地调用该函数本身,以实现层次数据结构的查询和访问。
在函数中直接调用函数本身,称为直接递归调用。
在函数中调用其它函数,其它函数又调用原函数,这就构成了函数自身的间接调用,称为间接递归调用。
而采用递归方法来解决问题,必须符合以下三个条件:
1、可以把要解决的问题转化为一个新问题,而这个新的问题的解决方法仍与原来的解决方法相同,只是所处理的对象有规律地递增或递减。
说明:解决问题的方法相同,调用函数的参数每次不同(有规律的递增或递减),如果没有规律也就不能适用递归调用。
2、可以应用这个转化过程使问题得到解决。
说明:使用其他的办法比较麻烦或很难解决,而使用递归的方法可以很好地解决问题
3、必定要有一个明确的结束递归的条件。
说明:一定要能够在适当的地方结束递归调用。
不然可能导致系统崩溃。
好知道是这样以后;我们来写一个众多教材上的程序:使用递归的方法求n!。
当n>1时,求n!的问题可以转化为n*(n-1)!的新问题。
比如n=4:
第一部分:4*3*2*1 n*(n-1)!
第二部分:3*2*1 (n-1)(n-2)!
第三部分:2*1 (n-2)(n-3)!
第四部分:1 (n-4)! 4-4=0,得到值1,结束递归。
我给的源程序如下:
#include <stdio.h>
int fac(int n)
{int c;
printf("now the number is %d ",n);
getchar();
if(n==1 || n==0) c=1;
else c=n*fac(n-1);
printf("now the number is %d and the %d! is %d",n,n,c);
getchar();
return c;}
void main()
{ int n=4;
printf("result is %d.\n",fac(n)); }
可以看到,加上两条printf()和getchar()语句后,可以察看各级调用及其中间答案,很清楚的看到程序的执行过程。
运行结果如图1所示,当主函数第一次调用fac()函数的时候,由于n=4不等于0和1,并不立即返回结果1,而是执行c=n*fac(n-1),用实参n-1(值为3)调用fac()函数自己,即递归调用fac(3)。
于是进入第二层调用fac(),这时也没有得出结果,继续用实参n-1(值为2)调用fac()函数自己。
同样经过第三层调用后进入第四层调用,这时候n=1,算出1!=1,满足结束递归的条件,然后把得出的结果1返回给第三次调用的fac函数,得出2*1!=2,然后把结果2返回给第二次调用的fac函数,得出3*2!=6,最后第一次调用的fac函数根据第二次调用的返回值算出4!=4*3!=4*6=24,结束整个递归调用,得出最终结果并输出。
我们做事情,一般都是从头开始的,而递归却是从末尾开始的。
比如上面的函数,当n>1的时候,就只能求助于n-1,而(n-1)>1时,就求助于n-2,然后……直到(n-k)=1时,函数fac终于有了返回值1了,它再从头开始计算,然后一直算到n为止。
所以说,递归简直就是一个数学模型,它的工作过程就是自己调用自己。
以下是几点对递归的说明:
1、当函数自己调用自己时,系统将自动把函数中当前的变量和形参暂时保留起来,在新一轮的调用过程中,系统为新调用的函数所用到的变量和形参开辟另外的存储单元(内存空间)。
每次调用函数所使用的变量在不同的内存空间。
2、递归调用的层次越多,同名变量的占用的存储单元也就越多。
一定要记住,每次函数的调用,系统都会为该函数的变量开辟新的内存空间。
3、当本次调用的函数运行结束时,系统将释放本次调用时所占用的内存空间。
程序的流程返回到上一层的调用点,同时取得当初进入该层时,函数中的变量和形参所占用的内存空间的数据。
4、在开发过程中使用printf()和getchar()可以看到执行过程,并且可以在发现错误后停止运行。
很多人说所有递归问题都可以用非递归的方法来解决,能不用递归就不用递归。
但是对于一些比较复杂的递归问题用非递归的方法往往使程序变得十分复杂难以读懂,而函数的递归调用在解决这类问题时能使程序简洁明了有较好的可读性,因此很多问题用递归可很容易解决。
同时由于递归调用过程中,系统要为每一层调用中的变量开辟内存空间、要记住每一层调用后的返回点、要增加许多额外的开销,因此函数的递归调用通常会降低程序的运行效率(在许多情况下,速度的差别不太明显)。
我曾经碰到过这样一个动物繁殖问题:若一头小母牛,从出生起第四个年头开始每年生一头母牛,按此规律,第n年时有多少头母牛?
如果不用递归函数来做,每当母牛到第4岁的时候才会生下一头小母牛,所以,每年增加的新的1岁小母牛都是上一年3岁的母牛加上4岁的母牛生下数量之和,分析过程如图2所示
给出程序如下:
main()
{int i,n;
int f1=1,f2=0,f3=0,f4=0;
printf("please input how many years it past:\n");
scanf("%d",&n);
for(i=2;i<=n;i++)
{ f4=f4+f3;f3=f2;f2=f1;f1=f4;}
printf(“now you have %d cattle!\n “,f1+f2+f3+f4); }
程序虽然简短,但是可读性太差,不易理解。
那么如果用递归函数求此问题呢?
我们先写出函数表达式:f(n)=f(n-1)+f(n-3)
为什么f(n)=f(n-1)+f(n-3)呢,请看:
f(n)-f(n-1)=f(n-3)
因为第n年要比n-1年多的牛,都是大于三岁的牛生的小牛,而f(n-3)正是那些在n年大于三岁的牛,然后它们在第n年生下相同数量的小牛。
源代码如下:
#include<stdio.h>
int cattle(int ct,int n)
{ if(n<4) return (ct);
else return (cattle(ct,n-1)+cattle(ct,n-3)); }
main()
{int ct=1,n;
printf("please input how many years it past:\n");
scanf("%d",&n);
printf("you have %d cattle now!\n",cattle(ct,n));}
运行结果如图3所示:
可见,递归函数的主要优点是可以把算法写的比使用非递归函数时更清晰更简洁,而且某些问题,特别是与人工智能有关的问题,更适宜用递归方法。
递归的另一个优点是,递归函数不会受到怀疑,较非递归函数而言,某些人更相信递归函数。
编写递归函数时,必须在函数的某些地方使用if语句,强迫函数在未执行递归调用前返回。
如果不这样做,在调用函数后,它永远不会返回,造成无穷递归。
在递归函数中不使用if语句,是一个很常见的错误。
此外,象汉诺塔问题就只能靠递归才能解决,但是现实中很多问题都是比较简单的,没有象汉诺塔那么复杂,我们只要会用递归编程来为我们解决一些问题就行了,所以就不必深究了。