递归概念
简单的来说,递归就是在函数里面再调用它本身,其目的是把复杂的问题分解成与原问题相似但规模较小的问题来解决,这样大大减少了程序的代码量。
递归条件
递归是需要一个终止条件的,否则就是一个死循环。比如求\(x^n\),可以转化为\(x^n=x*x^{n-1}\),\(x^{n-1}=x*x^{n-2}\)...而它的小终止条件就是\(x^0\)。具体见代码:
int xn(int n){
if(n==1) return 1;//终止条件
else return x*xn(n-1);//递归
}
递归应用
讲到递归,那么就不得不提一道递归的经典题:汉诺塔问题。
大致意思就是把\(a\)柱的\(n0\)个盘子移到\(c\)柱上,期间只能小盘子在大盘子之上。
先从简单的三个盘子来看,具体步骤为 \(a\rightarrow c,a\rightarrow b,c\rightarrow b,a\rightarrow c,b\rightarrow a,b\rightarrow c,a\rightarrow c\)
如果把第3步,第4步,第7步拿出来看,那么可以把上面两个盘子看作一个整体在移动,就可以把三个盘子移动分解成两个盘子移动。
同理,如果是移动n$$个盘子,那么就是把其上面\(n-1\)个盘子移动。那么,原问题就变为:
- 欲将\(a\)柱的\(n\)个盘子移到\(c\)柱,就先把上面\(n-1\)个盘子到\(b\)柱,\(a\)柱为源柱,\(b\)柱为目标柱,\(c\)柱为过渡柱,记为\((a,b,c)\)
- 将\(a\)柱上的一个盘子移动到\(c\)柱
- 将\(b\)柱上的\(n-1\)个盘子移动到\(c\)柱上,记为\((b,c,a)\)
接着,就是它的终止条件。它的终止条件应该是当\(n=0\)时,就退出那层循环。具体代码如下:
void mov(int n,char a,char c,char b)
{
if (n == 0)//如果盘子数为0就推出
{
return ;
}
else
{
mov(n - 1,a,b,c);//把a盘移到b盘,中间借助c盘
cout << "move " << n << " from " << a << " to " << c << endl;//把大的一块放过去就cout
mov(n - 1,b,c,a);//把b盘移到c盘,中间借助a盘
}
}