|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
递归思想n和n-1的行为相同,且每个步骤都是可行的,就可以使用递归。
例如汉诺塔问题中的,移n个盘和移n-1所经过的步骤是一样的,并且移n个盘是以n-1个盘为条件的,由于移一个盘时是可行的,因此后面从一个盘开始叠加的步骤都是可行的。所以移n-1个盘也是可行的,所以移n个盘就是可行的。
递归关键是处理n和n-1的关系,尤其是共用参数的时候。
yidong($n, $one, $two, $three)这个函数表示n 从one 移到three的功能
相当于先n-1 个从one移到two,然后one移到three,最后是n-1 从two移到three
yidong($n-1, $one, $three, $two) one-three yidong($n-1, $two, $one, $three)
这是程序的表现形式
这是函数的表达式
这和数学表达式的关系有什么不同。
递归关键处理两个相邻的关系。
老实说,楼上的回答只能是误人子弟,令人越听越模糊,似乎递归算法是高深莫测的一样。其实递归很简单的,请看我的分析。
递归算法适用的两个条件:1.每个步骤的完成形式是一样的2.后一个步骤的完成情况依赖于前一个步骤的完成情况。
前提是:每个步骤都可执行的。
比如:
汉诺塔的递归算法:
移n个盘从a到c,相当于把n-1个先从a移到b,然后把1一个从a移到c,最后再把n-1个从b移到c.
那么我首先就要问,把n-1个先从a移到b是不是可行的?
先看前提,由于移动1个盘是可行的,移2个盘是依赖于移1个盘的,所以移2个盘也是可行的,移3个盘是依赖移2个盘,所以移3个盘也是可行的,移n个盘时,依赖于n-1个盘,如果层层分解那么最终将会转化为依赖1一个盘。所以把n-1个先从a移到b是可行的。
既然我确定把n-1个先从a移到b和n-1个从b移到c是可行的,那么我下面要做的就是找出两个相邻步骤的关系,就是说,找出一个能够表达二者关系的表达式。
假如 这个函数hanoi(int n,char one,char two,char three)表达把n个盘从a移到c的过程。
那么把n-1个先从a移到b就可以表示成hanoin_1(n-1,one,three,two ),a移到c printf("a--->c") ,把n-1个从b移到c可以表示成hanoi(n-1,two,one,three)
由于从1到n每个两个相邻的步骤都是这种关系,两种的依赖形式是:n个步骤
如果n为偶数的话:
hanoi(int n,char one,char two,char three){
hanoin_1(n-1,one,three,two );
move(one,three);
hanoin_1(n-1, $two, $one, $three );
}
而hanoin_1(n-1,one,three,two );里面又调用了hanoin_2(n-1,one,two,three);move(one,two);hanoin_2(n-1,three,one,two);
...hanoi1(1,one,three,two);move(one,two);hanoi1(n-1,three,one,two);
至于hanoi1函数的原型可以写成同样的形式hanoi1(int n,char one,char two,char three){
if(n == 1){
move(one,three);
}else{
hanoin_1(n-1,one,three,two );
move(one,three);
hanoin_1(n-1, $two, $one, $three );
}
}
既然n个函数的参数和结构的是一致的,那么可不可以用一个函数来代替上述的函数呢?
答案是可以的。为什么?因为所有编程语言都支持对这身的调用,如果不支持,那么它肯定是一个失败的语言。
递归的调用和普通函数的调用没什么区别,同样是为每个函数开辟一个新栈。
语言的设计者肯定是看到递归可以节省大量代码的这个优点而设计的。
所以说递归一点也不深奥,和普通函数的调用没有什么区别。如果没有那个终极条件,那么函数的嵌套将是无数层的,所以必须要有终极条件。
下面从应用的角度看递归函数。
|
|