定义(个人理解)
1.自己调用比自己小一个规模的自己。
2.有结束条件。
3.对问题的细化。
ps: 大家可以通过这个效应感性的感受一下递归。
德罗斯特效应:
************************************************************************************************************************************************
递归条件
当然并不是所有的问题都能够用递归来实现。能够实现递归,需要满足以下条件:
1.有递归公式。问题能够分解为一个一个于自身类似的小问题。
2.有确切的边界。能够最后分解为一个有确定解的问题。
辅助分析图:
个人觉得,这个图应该是能够比较清晰地反映递归的调用了。
我们可以把递归调用看作是在原本的f()函数中又添加了f()函数的代码,只是现在的参数与原来不同罢了。只有当到达边界的时候,函数才会一层一层的被返回。也就是一个一个的问题被完成返回后,最外层的函数才会真正被完成也返回。
不太懂?没关系,咱们从实例中去理解递归~
************************************************************************************************************************************************
经典例题(个人分析)
该排版由易到难,请各位看客根据自己的需求翻阅。
阶乘
问题描述:请输入一个n值,输出n!的值。
code:
运行结果:
变式1:完成Fibonacci数列
变式2:完成Ackerman函数
(答案在最后~)
是不是觉得递归很简单呢?下面咱们再继续吧~
****************************************************************************************************************
汉诺塔问题
问题描述:假设有3个分别命名为X、Y和Z的塔座,在塔座X上插有n个直径大小各不相同、按从小到大编号为1,2,...,
n的圆盘(如图所示)。现要求将X轴上的n个圆盘移至塔座Z上并仍按同样顺序叠排,圆盘移动时必须遵循下列规则:
(1)每次只能移动一个圆盘;
(2)圆盘可以插在X、Y和Z中的任一塔座上;
(3)任何时刻都不能讲一个较大的圆盘压在较小的圆盘之上。
请问如何移?要移多少次?
code:
运行结果:
如果感觉有点晕的话也可以:
1.采取最开始解释的方法去看,就是在原来最开始的函数中添加了代码。
2.带入实际数据进去跟着程序运行一遍。
3.看下面动图~
汉诺塔栈方法解决:http://www.cricode.com/304.html
****************************************************************************************************************
八皇后问题
问题描述:经典的八皇后问题,即在一个8*8的棋盘上放8个皇后,使得这8个皇后无法互相攻击( 任意2个皇后不能处于同一行,同一列或是对角线上),输出所有可能的摆放情况。
code:
#include <iostream>
using namespace std;
int c[20],n=8,cnt=0;
void print(){ //打印
for(int i=0;i<n;++i){
for(int j=0;j<n;++j){
if(j==c[i])cout<<"1 ";
else cout<<"0 ";
}
cout<<endl;
}
cout<<endl;
}
void search(int r){
if(r==n){ //当已经排到最后一个皇后的时候位置一定固定。【条件2】
print();
++cnt;
return;
}
for(int i=0;i<n;++i){ //r表示第几行
c[r]=i; //c[r]=i,表示第r行第i列
int ok=1;
for(int j=0;j<r;++j)
if(c[r]==c[j]||r-j==c[r]-c[j]||r-j==c[j]-c[r]){ //判断是否在同一列,是否在主对角线或副对角线上【条件1】
ok=0;
break;
}
if(ok)search(r+1); //r+1必定不在同一行,故不用判断是否在一行
}
}
int main(){
search(0);
cout<<cnt<<endl;
return 0;
}
运行结果部分截屏:
****************************************************************************************************************
Answer:
变式1:使用公式f[n]=f[n-1]+f[n-2],依次递归计算,递归结束条件是f[1]=1,f[2]=1。
变式2:使用公式Ack(m,n)=Ack(m-1,Ack(m,n-1)),依次递归计算,递归结束条件n=0时,Ack(m,n)=Ack(m-1,1);m=0时,Ack(m,n)=n+1。