递归是一种数学上分而治之的思想
递归需要有边界条件
当边界条件不满足时,递归继续进行
当边界条件满足时,递归停止
递归将大型复杂问题转化为与原问题相同
递归函数:
函数体内部可以调用自己
递归函数中存在自我调用的函数
递归函数是递归的数学思想在程序设计中的应用递归函数必须有 递归出口
函数的无限递归将导致程序栈溢出而崩溃
计算字符串的长度:
int strlen_r(const char* s) { if( *s ) { return 1 + strlen_r(s+1); } else { return 0; } }计算1~n的和:
#include <stdio.h> int Count(int n) { int sum = n; if( n >= 1) { sum += Count(n-1); return sum; } else { return 0; } }斐波那契数列递归解法:
int fac( int n) { if ( n == 1) { return 1; } else if(n == 2) { return 1; } else { return fac(n-1) + fac(n-2); } return -1; }
划重点:必须注意的是,递归肯定很爽,这样想着关键代码两三行就搞定了,注意这题的n是从0开始的:
if(n<=1) return n; else return Fibonacci(n-1)+Fibonacci(n-2);然而并没有什么用,测试用例里肯定准备着一个超大的n来让Stack Overflow,为什么会溢出?因为重复计算,而且重复的情况还很严重,举个小点的例子,n=4,看看程序怎么跑的:
由于我们的代码并没有记录Fibonacci(1)和Fibonacci(0)的结果,对于程序来说它每次递归都是未知的,因此光是n=4时f(1)就重复计算了3次之多。
Fibonacci(4) = Fibonacci(3) + Fibonacci(2); = Fibonacci(2) + Fibonacci(1) + Fibonacci(1) + Fibonacci(0); = Fibonacci(1) + Fibonacci(0) + Fibonacci(1) + Fibonacci(1) + Fibonacci(0);
在对时间和空间都有要求的情况下,可使用循环来进行求解:
int Fibonacci(int n) { int preNum=1; int prePreNum=0; int result=0; if( n <= 0 ) { return 0; } else if( 1 == n || 2 == n ) { return 1; } else { for(int i=2;i<=n;i++) { result=preNum+prePreNum; prePreNum=preNum; preNum=result; } return result; }
汉诺塔问题:
void han_move(int n, char a, char b, char c) { if( n == 1) { printf("%c --> %c\n", a, c); } else{ han_move(n-1, a, c, b); han_move(1, a, b, c); han_move(n-1, b, a, c); } } int main() { char a = 'A'; char b = 'B'; char c = 'C'; han_move(3, a, b, c); return 0; }小结:
递归是一种将问题分而治之的思想
用递归解决问题首先要建立递归的模型
递归解法必须要有边界条件,否则无解。
扫描二维码关注公众号,回复:
1059377 查看本文章