递归总结


最近看到递归,觉得真是种很神奇的想法,但是很直观,也很重要。

首先总结一下递归的思想。

首先,递归的应用规范,即:问题可以分解为一个以上的小问题,并且小问题和大问题有相同的表达形式

递归的优势来源于它的逻辑简单易读,而不是来自于它的运算速度,它的基本思想即对输入的参数是否为”特殊情况“(最小规模或者错误情况)进行判断,若是则返回,否则缩小规模,也就是缩小范围,进入下一个递归函数。

如汉诺塔问题:

现在有三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,现在把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方,请问至少需要多少次移动,设移动次数为H(n)。

首先我们肯定是把上面n-1个盘子移动到柱子C上,然后把最大的一块放在B上,最后把C上的所有盘子移动到B上,由此我们得出表达式:

H(1)  = 1

H(n) = 2*H(n-1)+1 (n>1)

那么我们很快就能得到H(n)的一般式:

H(n) = 2^n - 1 (n>0)

void tower(int n, char A, char B, char C)
{
	if (n == 1)
		cout<<A<<"->"<<C<<endl;;
	else
	{
		tower(n - 1, A, C, B);
		cout<<A<<"->"<<C<<endl;;
		tower(n - 1, B, A, C);
	}
}

可以看到函数内先对需要移动的数量进行判断,若等于1则为最小范围,也就是可以进行输出;若大于1的话,那移动转换成为两次小范围的转移,也就是上文的解释,于是该问题得到解决,而我们不需要去考虑缩小范围的函数的具体实现,我们只需要将逻辑搞清即可。

同时,在递归过程中,可以巧妙的借助全局变量对递归过程中的一下过程进行记录,从而实现问题的解答,同时,可以对多次进行的一些操作另写一个函数来实现,可以看如下例子:

梯有N阶,上楼可以一步上一阶,也可以一次上二阶。编一个程序,输出所有不同的走法。

等到楼梯走到最后两级的时候也就是问题的终点了,当n=1的时候,可以直接输出;当n=2的时候可以选择上两级台阶,也相当于问题的结束,但此时还有第二种可能也就是只上一级台阶,于是再一次进行递归;当n>2的时候,有两种走法,一种是上一级台阶一种是上两级台阶,故代码如下所示:

//记录上楼梯的路径;
static int stair[100];

void upstair(int n, int m)
{
	stair[m++] = n;
	if (n == 1)
	{
		printUpstair(m);
	}
	else if (n == 2)
	{
		printUpstair(m);
		upstair( n - 1, m);	
	}
	else
	{
		upstair( n - 1, m);
		upstair( n - 2, m);
	}
}

void printUpstair(int t)
{
	for (int i = 0; i < t; i++)
	{
		cout<<stair[i]<<"->";
		if (i % 10 == 0 && i != 0)
			cout<<endl;
	}
	cout<<"0"<<endl;
}
我们声明了一个全局数组用于记录每一步分别走到哪级台阶上,同时函数printUpstair对走法进行输出。

总之,递归思想是一种很简洁的想法,可以抛开具体实现(交由一次次递归来实现),只需考虑好停止条件,和范围的缩小问题,也就是:对输入的参数是否为”特殊情况“(最小规模或者错误情况)进行判断,若是则返回,否则缩小规模,也就是缩小范围,进入下一个递归函数。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值