一步一步写算法(之递归和堆栈)

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】


    看过我前面博客的朋友都清楚,函数调用主要依靠ebp和esp的堆栈互动来实现的。那么递归呢,最主要的特色就是函数自己调用自己。如果一个函数调用的是自己本身,那么这个函数就是递归函数。

    我们可以看一下普通函数的调用怎么样的。试想如果函数A调用了函数B,函数B又调用了函数C,那么在堆栈中的数据是怎么保存的呢?

函数A    ^
函数B    |    (地址递减)
函数C    |
    如果是递归函数呢,举一个简单的递归函数为例:

int iterate(int value)
{
	if(value == 1)
		return 1;
	return value + iterate(value -1);
}
    下面我们使用一个函数进行调用,看看会发生什么情况?

void process()
{
	int value = iterate(6);
}
    看看此时内存堆栈是什么样的?

iterate(int 1) line 96
iterate(int 2) line 97 + 12 bytes
iterate(int 3) line 97 + 12 bytes
iterate(int 4) line 97 + 12 bytes
iterate(int 5) line 97 + 12 bytes
iterate(int 6) line 97 + 12 bytes
process() line 102 + 7 bytes
main() line 108
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817067()
    大家也看到了上面的代码,递归函数和普通的函数也没有什么差别。除了自己调用本身之外,他就是一个普通的函数。那么这个函数递归到什么时候返回呢?这就是递归函数的关键了。我们看到iterate函数到1就停止了,所以上面的堆栈在(value == 1)即return。所以一个递归函数最关键的部分就是两点:(1)递归策略;(2)函数出口。

    看到这里,大家可能感到递归函数不过如此,事实上也是这样。但是,还有一点大家需要牢记在心,递归的深度是我们必须考虑的一个问题。只有递归深度在一个可控的范围内,那么整个递归过程都是可控的。那什么时候不可控呢?那就是递归深度超过了一定的数字?这个数字和具体的线程堆栈长度有关?等到堆栈溢出了,那么获得的数据已经失去了真实性,所以也就没有意义了。

    我们把上面的问题推广一下,如何用自己定义的堆栈模拟上面的递归调用呢?这样既能满足递归的属性,又能确保函数深度可控。

    大家可以先写一下自己的方案,下面只是我个人的一个思路。

int iterate(int value)
{
	int count = 0;
	int number  =0;

	push(value);
	while(-1 != (number = pop()))
	{
		if(1 != number)
			push(number -1);
		count += number;
	}

	return count;
}



【预告: 下面一篇博客介绍算法和内存】

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式-老费

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值