C语言:汉诺塔递归的代码讲解

https://mp.csdn.net/mp_blog/creation/editor/135856751?not_checkout=1

什么是汉诺塔?

汉诺塔起源于印度的一则古老传说。 法国数学家爱德华·卢卡斯曾编写过一个印度的传说。 在世界中心贝拿勒斯(传说在印度北部)的圣庙里,有一块插着三根宝石针的黄铜板。 印度教的主神梵天在创造世界时,从下到上地在一根宝石针上串上了由大到小的64片金片,这就是汉诺塔的雏形。

如图是一个汉诺塔,玩法就是将A(起点)柱子的三个圆盘通过B(辅助点)全部移到C(终点)的柱子上

规则:

每次只能移动一个圆盘。

每次只能移动最顶端的圆盘。

只能是小的叠在大的上面。

(情况1)我这里从简单的一个圆盘开始:

如图在A(起点)柱上只有一个圆盘,目的是移到C(终点)柱上面,方法是把盘子直接从A移到C去,这是最简单的情况 。

(情况2)如果有两个圆盘又该怎么移动呢?

                   

步骤1:我们将A(起点)小圆盘移到B(终点)上。

步骤2:将A(起点)上的大圆盘移到C(终点)

步骤3:将B (起点)的小圆盘移到C (终点)上。

最后完成移动。


(情况3)移动n个盘子

知道了移动两个盘子之后那怎么移动n个盘子呢?

 

我们可以将整体看成两部分,一部分是最底层的盘子前n-1个盘子,这样我们就可以用移动两个盘子的思想来移动这n个盘子

想要让A柱所有的盘子移到C柱上,首先需要让A柱最底层盘子上n-1个盘子先移到B柱上,再将A柱的大盘子移到C柱上,最后再把B上的n-1个盘子移到C柱上。

步骤1:把前n-1个盘子整体从A(起点)经过C(辅助点)移到B(终点)上。

辅助点是帮助把n-1的圆盘移动到终点柱的柱子。

                                                

步骤2:把A(起点)上最大的盘子移到C(终点)上。


步骤3:把前n-1个盘子从B(起点)经过A(辅助点)到C(终点)


如果忽略这n-1盘子的移动情况,这些步骤和情况2的步骤完全一样。

那如何移动这n-1个盘子呢?

其实思想还是一样,我们还是可以把其看做成两部份(n-1个盘子n-2个盘子

采用情况2的思想。

步骤1:将n-2个盘子从B(起点)经过C(辅助点移到A(终点)

步骤2:将n-1个盘子从B(起点)移到C(终点)

步骤3:将n-2个盘子从A(起点)经过B(辅助点移到C(终点)

我们现在所做的就是把大问题转换成小问题,最开始的大问题就是将A(起点)柱上的n个盘子通过B(辅助点)移到C(终点)柱上经过上面步骤1和步骤3 ,把问题变小将n-1个盘子从B柱(起点)通过A柱(辅助点)移到C柱(终点)上再经过上面步骤1和步骤3 ,把问题又变小将n-2个盘子从A柱(起点)经过B柱(辅助点)到C柱(终点)上。

    

一直这样下去直到变成只剩一个盘子时,已经不能再细分了,经过步骤2,将最后一个圆盘直接移到C(终点),也就完成移动了。

我们先用伪代码写一遍
//假设有n个盘子,定义一个函数:
void hanoi(int n,char A,char B,char C)//函数目的是将n个盘子从A(起点)柱通过B(辅助点)柱,移到C(终点)柱。
{
    if(n==1)//如果n=1,只有一个盘子(最简单的情况),限制递归的条件
    {
    printf("%c->%c\n", A, C);//直接将这一个盘子从A柱移到C柱
    }
    else//如果是n>1个盘子
    {
    hanoi(n-1,A,C,B);//步骤1将n-1个盘子从A柱通过C柱移到B柱,通过调用自身。

      printf("%c->%c\n", A, C);//步骤2将第n个盘子从A柱移到C柱。

     hanoi(n-1,B,A,C步骤3将n-1个盘子从B柱通过A柱移到C柱,调用自身。
    }

注意:这里ABCABC的含义并不相同。

A代表A柱子,B代表B柱子,C代表C柱子。

void hanoi(int n,char A,char B,char C) 这里的3个形参ABC是固定的,这里的A表示起点B表示辅助点C表示终点,每一次递归A,B,C三个参数代表的柱子都在不断的改变,即使函数printf里面看似只从AC进行输出,其实真正打印出来的各种移动情况都有,这里很容易混淆,导致看不懂代码。

代码如下

#include<stdio.h>
void hanoi(int n, char A, char B, char C)
{
	if (n == 1)
	{
		printf("%c->%c\n", A, C);
	}
	else
	{
		hanoi(n - 1, A, C, B);
		printf("%c->%c\n", A, C);
		hanoi(n - 1, B, C, A);


	}

}
int main()
{
	int n = 0;
	printf("请输入你的盘子数:");
	scanf("%d",&n);
	char A = 'A';
	char B = 'B';
	char C = 'C';
	hanoi(n,A,B,C);
	return 0;
}

我可能阐述的不是很好,如果有写的模糊的地方,请各位大佬们指出来,让我及时改正,谢谢大家。

                                                                                                

                                                                                                                                                                       

                                                                             

                                                                                                                

                                                                                                                                                                                                                                                                                                                   

                       

  • 39
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值