狭义递归与广义递归算法

2002年10月12日,我买了一本GoF的《Design Patterns》。4年多下来,我并没有看完那本小书。一方面是因为那本书的内容经过Base64编码处理过,看不见一个汉字;另一方面也是确实没有足够的时间一口气看完。幸好里面的每一节都比较分立,所以我一上厕所就容易想到它。书已经没有以前那么新了,上面所过之处写了些笔记。不过,还能看出来,曾经它是一本新书。

2007年4月26日,同往常一样,下午6:40左右,我又去上自习去了。那是一间挺休闲的酒吧,没有跳钢管舞的也没有走秀的。每天窗外的风景(对那些混凝土的抬举叫法)每天都一样,今天也毫不例外的没有给我任何惊喜。人行道上的人们无声的来来往往,不知道是他们无聊还是我无聊,总之我觉得有一方可能比较无聊。正如你早猜到了的,无聊的那个人正是我,因为我正在酒吧看那本《Design Patterns》。

在Decorator的时候,看到那个链式调用结构,想到了我曾经设计的环形分布式数据库解决方案,后者是对前者的一个顺理成章的扩展。然后就想到了递归,那个东西和调用这个词关系非同一般。也许很多人写过程序的人都会说,现实中用递归的地方很少,那些商务逻辑基本上就是顺序、条件和循环。的确,要用到递归的地方不是很常见。

你应该有点厌烦了,特别是像我同事那样的粪清,容不得别人说半句废话。那么,我们还是递归一下吧。你应该很熟悉这个词了,说的简单一点就是函数调用自身。嗯,确实是这样。不过这只是一半而已。我们看看下面的两段程序:

1、function operate() {
operate();
}

2、function operate_another() {
}
function operate() {
operate_another();
}

你觉得哪个是递归调用呢?是的,你很聪明,一眼就看出来了。第一个不是,第二个是。第一种调用方式,operate函数直接调用本身,它把调用直接传给了另外一个自己,这样一只传下去。我们换个词汇,把这个“传”叫做“递”。那么,就是说,第一种情况下,函数调用被逐层的“递”到另外一个自己。这是“递归”的一半,它没有回头路,永远的去了。你并没有上当,我不是在咬文嚼字。这要感谢中文,它不像英语的recursive一样,给人的只能是困惑。一个RE加一个CURSIVE,比较没意思。第一种情况被判死刑,因为它只实现了递归中的“递”,也就只能算半个递归。半个人算人吗?应该不算吧,我想,对人的分割算法没有怎么研究。所以,我还是忍痛把第一种情况叫做了“不是递归”。

第二种情况下,operate函数将控制递给operate_another,operate_another接着啥事都没做就返回了。这句话中出现了两个关键词,一个是“递给”,另一个是“返回”。这样,控制流程上就有了递和归,所以我承认它的合法递归地位。但为什么我们平时不把所有的这种子程序调用叫做递归调用呢?我想多半是因为太平凡了,以至于如果都承认他们递归我们会累得吐血。所以呢,大家就把第一种情况作了改造,让它担当起了递归的真正英雄。哎,可悲啊,该当递归的每当上,不该当的当上了。以嘎的社会,太乱了!

那么,所谓的狭义递归,就被哪个调用自己,并在适当的时候返回的东西给夺去了。具体例子我就不用写出来了,写过阶乘的递归的应该不在少数了。而我将第二种情况叫做广义上的递归。但因为它确实太广了,还是要做一点修剪。所以,我把调用实体具有相似结构并逐层传递控制而且适当的时候返回的那种调用结构叫做广义递归。就像Decorator模式,核心Widget被添加上一串Decorator。调用是从Decorator链的起始点开始的,然后逐级传递,到核心的Widget的时候开始逐级返回。这是一种链条状的结构,还可以扩展成环形。

以前碰到一个分布式数据库的实现问题,当时用的是环状的递归调用结构。因为每个数据库都是一样的,但系统可能会时不时的加减系统中的数据库个数。并且,最重要的一点,调用的开始点不确定。人工发起的动作可能从任何一个数据库开始,并遍历系统中所有的数据库。这种情况下,只能用环状的结构。调用存储过程的时候传递一个计数参数,它在每次调用下一个数据库的相应存储过程的时候都会先加一。并且,别忘记了归的过程。当计数器达到系统中的数据库个数的时候就不再往下传递。这样,所有的数据库都有同样的存储过程。

另外,还可以扩展成树形的结果。做竞赛题的时候用到的回朔搜索算法就是了。12点过了,吃饭去。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值