经典递归问题——易懂的汉诺塔~2020.7.1学习笔记

    技术2022-07-10  74

    汉诺塔是非常经典的递归问题,许多学校在新授C语言课程当中的递归部分时,都会拿汉诺塔当作例子。汉诺塔的规则不必多说,简单提一嘴就是有三个轴,一开始所有的圆盘都摞在A轴上,且这些圆盘的直径由上至下递增,目标是将所有圆盘都移至C轴,一次只能移动一个圆盘,并且大的圆盘永远在下。 话不多说,直接上代码。

    #include <iostream> #include <cstdio> using namespace std; void hanoi(int n,char x,char y,char z){ if(n==1){ cout<<x<<"-->"<<z<<endl;//n==1时为递归退出条件,A轴上只剩一个圆盘了,显然要 //将他移到C轴。 return ; } hanoi(n-1,x,z,y);//将n-1个圆盘由A轴移到B轴 cout<<x<<"-->"<<z<<endl;/*hanoi函数都是将x位置的函数移往z位置,更改移动轴的方法 是在函数递归时改变传入的实参顺序。*/ hanoi(n-1,y,x,z);//将n-1个圆盘由B轴移到C轴 } int main() { int n; cout<<"请输入需移动的盘子数:"; cin>>n; hanoi(n,'A','B','C'); return 0; }

    问题的求解核心是递归,经过分析,递归的退出条件显然是A轴只剩下一个圆盘的时候,只需将这个圆盘移至C轴即可。 何时调用递归函数呢?显然要将前n-1(此处的n为A轴初始圆盘总量)个圆盘按照规则先移至B轴,待A轴上的最后一个圆盘移走,再将B轴上的圆盘按规则移至C轴,此处的回溯很难用语言表述清楚,若读者初学C语言或初探递归问题,不妨自己动手模拟一下,递归见得多了,自然也就会了(本人就是)。此处举输入数据n为3时为例模拟一下。

    n==3时,执行以下语句:

    hanoi(n-1,x,z,y);//将n-1个圆盘由A轴移到B轴

    此时,通过编译器的调试功能可知,进入该函数后n==2,x,z,y为A,C,B即此时若移动圆盘,是将A轴最顶端的盘移到B轴上。暂且记这一层为第二层,上一层为第一层。 显然于第二层,没有递归的退出条件,执行下述最低端语句。

    void hanoi(int n,char x,char y,char z){//不执行 if(n==1){//不执行 cout<<x<<"-->"<<z<<endl;//n==1时为递归退出条件,A轴上只剩一个圆盘了,显然要//不执行 //将他移到C轴。 //不执行 return ;//不执行 }//不执行 //不执行 hanoi(n-1,x,z,y);//将n-1个圆盘由A轴移到B轴 //执行这一句, //除最后一句上面的语句在n==2时尚未达到执行条件

    进入hanoi(n-1,x,z,y);此时n==1,记这一层为第三层,xyz的次序重新变为ABC,进入这条语句,达到递归的退出条件,执行cout<<x<<"-->"<<z<<endl;将A轴顶盘先移至C轴,return,回到第二层。 此处要注意,第二层是在hanoi(n-1,x,z,y);进入语句的,当从第三层退出时,仍在第二层的此处,而不是从头开始,这便是递归最难理解之处了。

    void hanoi(int n,char x,char y,char z){ if(n==1){ cout<<x<<"-->"<<z<<endl return ; } hanoi(n-1,x,z,y); cout<<x<<"-->"<<z<<endl; hanoi(n-1,y,x,z); }

    因此,之后执行的是将cout<<x<<"-->"<<z<<endl;,程序位于第二层时,xyz的顺序为ACB,故此将A轴顶盘移至B轴。之后执行hanoi(n-1,y,x,z); 重回第三层,只不过此时的第三层xyz顺序有所改变,变为CAB,即将C盘移至B盘之后return,回到第二层。 同上,回到第二层后语句指针(为方便说明问题自己发明的说法,无实际意义)仍在hanoi(n-1,y,x,z);,其之后没有可执行的语句了,显然到达函数尾,函数调用结束,即隐式地调用了return,返回第一层,返回第一层后,语句指针仍在hanoi(n-1,x,z,y);,详见下代码块,

    void hanoi(int n,char x,char y,char z){ if(n==1){ cout<<x<<"-->"<<z<<endl return ; } hanoi(n-1,x,z,y);/*!从第二层退回第一层时,程序仍从这儿开始执行语句!*/ cout<<x<<"-->"<<z<<endl;//下一条语句 hanoi(n-1,y,x,z); }

    至此,相信你已经理解了递归的简单原理与应用,后面的代码解释笔者就略过了,留给读者自行挖掘。运行结果如下: 码文不易,您给点个关注?

    Processed: 0.022, SQL: 8