1、什么是递归:
C允许函数调用他自己,这种调用过程称为递归(recursion)。递归有时难以理解,有时又方便实用。结束递归是使用递归的重难点,因为如果递归代码中没有终止递归的条件部分,一个调用自己的函数就会无限的递归。
2、递归代码的演示:
#include<stdio.h> void f(int n) //递归函数 { printf("%d:%p\n", n, &n); //#1 打印n及对应的地址 if (n < 3) //终止递归的条件 { f(n + 1); //自己调用自己 } printf("%d:%p\n", n, &n); //#2 打印n及对应的地址 } int main() { f(1); //创造函数 return 0; } //printf中的%p及&n;就是打印n对应的地址。
分析:main函数先调用了f(1),后代码进入函数中 #1 打印对应的1及其地址,再进行判断1<3,条件成立;函数进一步调用了自身即f(2),代码进入函数中 #1 打印对应的2及其地址,再进行判断2<3,条件成立;函数进一步调用了自身即f(3),代码进入函数中 #1 打印对应的3及其地址,判断3<3,条件不成立,函数不再调用自身,代码走到了 #2 的位置并打印了3及其地址;此时,第3级调用结束,被传回第2级函数(因为是第二级函数f(2)调用他的);而第二级函数也继续执行后面的代码 #2 后结束被传回第一级f(1)又执行了 #2 ,至此调用结束也就是递归结束。
3、递归的原理:
每一级函数调用都有自己的变量,也就是第n级对应的n是不同的,只是变量名相同;每次函数调用都会返回一次,即当函数执行完毕之后就会传回上一级函数。
4、递归与循环:
到这里不难发现其实递归与循环有很多思想上的相识之处。一般而言,可以用循环的地方通常也都可以用递归,有时循环更容易理解,而有时却是递归更加方便简洁。
例如编写一个算阶乘的程序。
#include<stdio.h> void fun(int n) //使用循环的函数 { int sum = 1; for (int i = n; i > 1; i--) { sum *= i; } printf("n的阶乘是%d\n", sum); } int fun1(int n) //使用递归的函数 { int sum; if (n > 0) { sum = n * fun1(n - 1);//调用自身 } else sum = 1; return sum; } int main() { int n; scanf("%d",&n); fun(n); int ret=fun1(n); printf("n的阶乘是%d\n", ret); return 0; }
5、递归的优缺点:
优点是为某些编程问题提供了简单的解决方案,复杂程序精简化。
但是缺点是递归算法比起循环来会快速消耗内存资源,因为再调用自身时也在不断创建新变量,而且阅读和理解的体验感极差(特别是多重递归等),直接劝退多少小白(!!!)
最后的总结:
在c语言中递归一种就是用来编写需要一直调用自身函数且在一定的条件下需要停下的程序(函数)的编程技巧。利用递归可以用简单的程序来解决一些复杂的问题。比如:斐波那契数列、汉诺塔、快排等问题。但是理解难度较大,需要多敲代码,多思考,不能有抗拒心理。