浅析汉诺塔递归过程

           这两天一直在看汉诺塔的递归过程,花了点时间把这个程序仔细分析了几遍,在执行过程的分析中遇到了些问题,上网查了查,也没有找到比较满意的答案,所以就硬着头皮自己解决了,我想我遇到的问题也许很多人也会遇到,于是我就把我对汉诺塔递归过程的分析写了出来,希望对一些人有所帮助,当然,开始前还是声名一下,我这是菜鸟文章,自认为是高手的,还请绕道,谢谢。

废话不多说,上代码:

#include<stdio.h>

void move(char x,char y)

{

     printf("%c-->%c/n",x,y);

}

void hanoi(int n,char one,char two,char three)

{

     if(n==1)

     {

         move(one,three);

     }

     else

     {

          hanoi(n-1,one,three,two);

          move(one,three);

          hanoi(n-1,two,one,three);

     }

}

void main()

{

       int m;

       printf("请输入盘子数:");

       scanf("%d",&m);

       printf("%d个盘子的移动步骤为:/n",m);

       hanoi(m,'A','B','C');

}

 

    可以看出,代码是由三部分组成:move()函数、hanoi()函数和main()函数,其中move()函数是用来输出表示输出方式的字符串的,hanoi()函数是用来控制盘子移动的(要明白,这里的控制盘子移动不是真的在移动盘子,只是控制盘子输出方案的),main()函数就不多说了。

    

问题主要集中在hanoi()中,下面我来具体分析:

我以n==3为例

 

1      void hanoi(int n,char one,char two,char three)

{

            2            if(n==1)

                          {

            3                     move(one,three);

                          }

            4            else

                          {

            5                    hanoi(n-1,one,three,two);

            6                    move(one,three);

            7                    hanoi(n-1,two,one,three);

                          }

      }

 

 在main()函数中,hanoi(n,’A’,’B’,’C’)表示的是n个盘子从A柱经过B柱移到C柱,这里我们只分析n==3的情况。记住,这个hanoi里的参数是实参,实参传递到第1行中的形参,此时,one=Atwo=Bthree=C。然后走第2行,n不等于1,所以执行else中语句,到第5行,又有一个函数调用,这时n变成2,第5行为hanoi(2,’A’,’C’,’B’),这里一定要理解,然后这一个hanoi里的参数成为实参,接着就是所谓的递归,调用自身,所以程序回到第1行,此时,one=Atwo=Cthree=B,然后和刚才一样,n不等于1,走第5行,这时第5行为hanoi(1,’A’,’B’,’C’),很刚才一样,这里面的参数是实参,就又回到第1行,此时,one=Atwo=Bthree=C。接下来走第2行是发现n==1,所以执行move(one,three),也就是会输出AàC,这也就是程序输出的第一个步骤。

这之后就是我当初没有理解的地方了,第3行执行完后再执行哪儿呢?注意了,当n==1后,第3行其实相当于第5hanoi函数的函数体,第3行执行完后就相当于第5行执行完毕,接下来就开始执行第6行,也许有人会说了,执行了if语句里的程序怎么又执行else里的呢?在这里,就需要大家记住这是个递归过程,这里确实开始有点难理解,所以需要大家好好的想想了。

好,接着刚才的,执行第6行,move(one,three),这时,又有个问题出现了,这里move中的onethree分别是什么呢?也许有人会说,刚才第5行的A,B,C传给第1行后one就是A了,three就是C了呀,在这里,请注意了,第5行的onetwothree和第1行的onetwothree是占用的不同的存储空间,只是名字一样罢了,这个调用只是传递值,而不会传递地址,所以第6move中的one=A,three=B,所以程序的第二个步骤终于出现了:AàB

OK,继续,搞懂了上面的值传递后,接下来第7行中的参数就应该知道是什么了吧,我还是写出来吧,hanoi(1,’C’,’A’,’B’)。同样,这是实参,调用到第1行,就是one=C,two=A,three=B,然后就是第3行,程序的第三个步骤就出来了:CàB

到这里,又到了不好理解的地方了,以上的步骤主要是完成了当n==1时的情况,而hanoi(n=1)中包含三个部分:一是hanoi(n=2,one,three,two),二是move(one,three),三是hanoi(2,two,one,three);而hanoi(n=2,one,three,two)中又包含{ hanoi(1,one,three,two)move(one,three)hanoi(1,two,one,three)},所以,以上的步骤也就是说完成了大括号中的内容,接下来就要开始执行和它并列的move(one,three),这里一定要好好琢磨琢磨,理清这里面的层次,搞懂为什么要执行move(one,three)。好了,搞懂之后,执行move(one,three),输出程序的第四个步骤:AàC(注意要搞清楚这里的onethree得到的值是从hanoi(n=3,’A’,’B’,’C’)中来的,因为这是和hanoi(n=2,one,three,two)并列的)

因为move中没有包含其他的语句,所以接下来就开始执行最后一个并列的hanoi函数,也就是hanoi(2,two,one,three)(此时,one=Atwo=Bthree=C)。这个就和先前最开始的是一模一样的,因为n不等于1,所以到第1hanoi(2,B,A,C),往下到第5行:hanoi(n=1,B,C,A),在到第3行(接下来我就不详细写了),第五个步骤出来:BàA

再到第6行,第六个步骤也就出来了:BàC

然后同样,走第7行(hanoi(n=1,A,B,C)),理所当然的,最后一个步骤出来了:AàC

 

至此,当n==3时,汉诺塔的整个递归过程就结束了,对于我们初学者,过程是有点复杂,所以每一步我都尽可能写得详细,希望对大家有所帮助。

当初困扰我的主要有两个方面:

1、         对于递归的理解问题,递归中包含的if else等语句很容易打乱我们对于执行顺序的分析,所以一定要搞清递归是个怎样的过程。

2、                要分清楚实参和形参,搞懂值传递的实质,只有这样才能明白onetwothreeA,B,C是怎么对应的。

 

这两个方面搞清楚了,整个过程也就很容易理解了。

最后,我想说毕竟我才学到函数这一章,很多东西都不知道,所以其中也许会有理解上的错误也说不定,如果有人发现错误,还请指教了,谢谢。

 

 

 

                                                                                                                                                  2010416

                                                                                                                                                         马克

### 汉诺塔递归实现的过程解释 汉诺塔问题的核心在于利用递归的思想来解决问题。以下是关于如何通过递归实现汉诺塔的具体过程: #### 1. 基本概念 汉诺塔问题的目标是从起始柱(通常称为 A)将所有的盘子移动到目标柱(通常称为 C),借助辅助柱(通常称为 B)。每次只能移动一个盘子,并且任何时候大盘都不能放在小盘之上[^4]。 #### 2. 递归分解 对于 n 层的汉诺塔问题,可以将其分为三个主要部分: - 将前 \(n-1\) 个盘子从起始柱 A 移动到辅助柱 B,使用目标柱 C 作为中间过渡。 - 将第 \(n\) 个盘子直接从起始柱 A 移动到目标柱 C。 - 再次将 \(n-1\) 个盘子从辅助柱 B 移动到目标柱 C,这次使用起始柱 A 作为中间过渡[^1]。 这种分而治之的方法正是递归的本质所在。 #### 3. 结束条件 当盘子数量为 1 (\(n=1\)) 时,不需要进一步拆解问题,只需直接将该盘子从起始柱移动到目标柱即可。这是递归的终止条件[^2]。 #### 4. Python 实现代码 下面是基于上述思路的一个标准递归实现代码示例: ```python def hanoi(n, source='A', auxiliary='B', target='C'): if n == 1: print(f"Move disk 1 from {source} to {target}") return # Step 1: Move (n-1) disks from source to auxiliary using target as a helper. hanoi(n - 1, source, target, auxiliary) # Step 2: Move the nth disk directly from source to target. print(f"Move disk {n} from {source} to {target}") # Step 3: Move (n-1) disks from auxiliary to target using source as a helper. hanoi(n - 1, auxiliary, source, target) # Example usage with 4 disks hanoi(4) ``` 这段代码展示了完整的递归流程,其中 `print` 函数用于记录每一次具体的移动操作。 #### 5. 时间复杂度分析 汉诺塔问题的时间复杂度可以通过其递归关系得出。假设 \(T(n)\) 表示解决 \(n\) 层汉诺塔所需的步数,则有如下递推关系: \[ T(n) = 2 \cdot T(n-1) + 1 \] 初始条件为 \(T(1) = 1\)。由此可得最终时间复杂度为 \(O(2^n)\),即指数级增长[^3]。 --- ###
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值