栈与递归——2018/01/07思考

栈与递归

继昨天写完栈的简单应用——四则运算之后,我对栈的兴趣又变浓了,尤其是昨天在看到栈与递归这个问题时,心中更是一咯噔,我们都知道递归对内存的耗费是比较大的,而计算机在函数调用过程中与栈相似,因此递归是可以通过栈来实现的,从而提高效率(当然循环有时候也是可以实现的,可是我就想用栈,你管我~),所以在我下午吃了一下午鸡(跳了一下午伞)之后,“良心备受谴责”,特意晚上重回图书馆。回到图书馆后本来是打算接着早上的“图”开始继续学习的,可是我对栈实现递归的热爱不允许我去继续看“图”,所以我才来到这里,写一篇关于栈的应用——递归。

在学完计算机系统基础之后,我对计算机的原理又有了新的认识(其实以前什么都不知道尴尬),程序在调用一个函数时,先称调用者为“父函数”,被调用者为“子函数”,当父函数在调用子函数时,往往需要先将自身当前的状态保持不变,然后开始执行子函数,执行完子函数以后,又重新返回继续父函数。函数调用这个过程就类似于“先调用的后完成,后调用的先完成”,这于栈“先进后出”的特性相似。递归,其实就是调用自身或间接调用自身。因此便可以通过一系列对入栈出栈的操作来模拟实现递归调用这个过程。

刚刚思考了半天,没想出来,于是看了一篇博客:http://blog.csdn.net/chinainvent/article/details/1317024,多谢这位牛人指点迷津。

下面我以斐波那契数列为例来写一下对栈实行递归的理解:

递归实现的过程:

1.将一个大问题转化为小问题:f(4)=f(3)+f(2);

2.小问题是否可以求解,若不能,继续转化:f(3)=f(1)+f(2);

3.小问题可以求解,返回问题的解:f(3)=f(1)+f(2)=1+1=2;

4.继续返回问题的解直到求出大问题的解:f(4)=f(3)+f(2)=2+1=3;


问题的本质:f(4)=f(3)+f(2)=f(2)+f(1)+f(2);

int fib(int n){
	if(n==1 || n==2)
		return 1;
	else
		return fib(n-1)+fib(n-2);
}

栈实现:

1.将大问题入栈:f(4);栈状态[f(4)]
2.弹出栈顶(大问题):f(4);栈状态[ ]
3.无法求解大问题,将大问题分解:f(4)=f(3)+f(2),并入栈f(2),f(3)(注意:此问题对先后入栈先后顺序没有要求,但某些问题有先后顺序要求,应将先执行的后入栈,再次强调,注意顺序!);栈状态[f(2) f(3)]
4.弹出栈顶元素(大问题,注意这个大问题是相对于可以直接解决的问题来讲,实际上已经是小问题了):f(3);栈状态[f(2)]
5.无法求解大问题,将大问题分解:f(3)=f(2)+f(1),并入栈;栈状态[f(2) f(2) f(1)]
6.弹出栈顶元素:f(1),可解决,进行操作:result+=f(1)=1;(不同问题的操作不相同,此问题实际上是求和,因此为‘+’);栈状态[f(2) f(2)]
7.继续弹出...基本方法已经说明,后面省略


int fib_stack(int cur){
	int result=0,n=cur;
	stack<int>f;
	f.push(n);
	while(!f.empty()){	//栈非空 
		n=f.top();		//取出栈顶元素 
		f.pop();
		if(n==1 || n==2){//判断小问题是否可以解决 
			result+=1;
		} 
		else{			//将大问题分解 
			f.push(n-1);//将小问题入栈 
			f.push(n-2);//将小问题入栈 
		}				//注意顺序,某些问题对执行顺序有要求 
	}
	return result;
}

总结:递归调用无非就是重复调用自身来重复某一个动作,函数的参数即为这个动作的数据,因此我们利用栈实现递归只需要利用栈来存储这个动作所用的数据,然后再取出数据来执行这个动作。
int fib(int n){
	if(n==1 || n==2)
		return 1;
	else
		return fib(n-1)+fib(n-2);	//执行"+"这个动作 
}

int result=0;

void f(int n){
	result+=n;
}

int fib_stack(int m){
	stack<int>f;
	f.push(m);
	while(!f.empty()){
		n=f.top();
		f.pop();
		if(n==1 || n==2)
			f(n);		//执行"+"这个动作 
		else{
			f.push(n-1);
			f.push(n-2);
		}
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值