长篇警告
全部都是在学习过程中自己的理解,若其中有误请及时提出,以便修改
递归是我们学习过程中必不可少的一部分,很多刚入门的同学无法理解递归的含义,或者只是知道这是一种自己调用自己的函数,但是并不知道原理以及原因。
在递归调用中,有直接调用自己和间接调用自己。无论是直接还是间接都是相同的,没有什么差别。
递归
在我看来的递归,就是将一个大问题拆分为自己本身与子问题的过程,然后逐步解决子问题(当自己本身没有子问题时即递归结束)。当子问题全部解决完,大问题也将轻而易举地完成。
可能上述的话有点不好理解,接下来我将用阶乘的例子说明!
在此定义一个递归函数fun()
int fun(int n)
{
if(1 == n)
{
return 1;
}
else
{
return n*fun(n-1);
}
}
假如此时需要计算4!
那么大问题就是解决4!,自身就是4,子问题便是3!
【说明】当知道3!的结果时,便可轻松解决4!。因此,可将大问题拆解为,“自己本身–>4”和“子问题–>3!”;
- 第一步:拆解为【 "4"和“3!”】
- 第二步:将3!作为下一个大问题,拆解【“ 3 ” 和 “ 2!”】
- 第三步:将2!作为下一个大问题,拆解【" 2 " 和 " 1! "】
此时1!再没有子问题,因此递归结束!!!
将所有的子问题与本身结合便可得出大问题的结果!
汉诺塔
汉诺塔很多在学习的时候并未真正的理解,或许只是知道原理,知道代码怎么写,但是完全凭借记忆力,背下来的代码!
接下来我就图形解读和代码解读!从原理到代码的一步一步的理解!
汉诺塔是学习递归中的经典例子之一!
首先我们需要知道物理中的一种方法便是"整体法"。利用上述所说,便是将所有的子问题看成一个整体,之后再慢慢解决。
汉诺塔图解原理
其中有3个柱子,为X、 Y、 Z。分别赋予其他名字。此时称X为移动柱,Y为借助柱,Z为目标柱子!
如图!假设此时有4个盘子,需要从X依次移到Z上。
此时将问题拆解。【自己本身–>第四个盘子从X到Z】【子问题–>前三个视为整体移到Y】
(此时前三个盘子在Y柱上,便称Y为移动柱)
继续将子问题拆解。【自己本身–>第三个盘子从Y到Z】【子问题–>前两个视为整体移到X】
继续拆解。【自己本身–>第二个盘子从X到Z】【子问题–>将最上面的盘子从X移到Y】
汉诺塔代码解读
因此,图的逻辑便为如此。接下来是代码的解读!
重点
第一个参数为盘子数,第二个参数是移动柱,第三个参数是借助柱,第四个参数是目标柱。每次的移动柱和借助柱都互换,所以每次函数调用时参数内容不同!!切不可认为每次移动柱与借助柱一成不变!!!
void hanoi(int n,char X,char Y,char Z)
{
if(1 == n)
{
printf("%c-->%c\n",X,Z);
}
else
{
hanoi(n-1,X,Z,Y);//将n-1个盘子从移动柱X,利用借助柱子Z,移动到目标柱Y上
printf("%c-->%c\n",X,Z);//将第n个盘子直接从X-->Z
hanoi(n-1,Y,X,Z);//将剩下的n-1盘子,从移动柱Y,利用借助柱X,移动到目标柱Z上
}
}
【说明】:在函数调用时,若此时该函数调用未全部执行完,就不会继续向下执行代码!