C语言解决汉诺塔问题(递归篇)

汉诺塔游戏如图:

 其规则是将TOWER1的所有方块移到TOWER3上,每次只能移动一个方块,最重要的是大的方块不能在小方块之上!!!

用递归实现解题步骤。刚开始接触递归对我而言实在太过抽象,这道题也是研究了好久,现在将我的解题思路写下来。已共分享

 首先要先理解这个游戏的玩法,也就是解题思路,先从最简单的开始如果第一个柱子(后文用a代替,以此类推)上就有一个方块,那就将a直接移到c就好,如果a是两个方块那就要先把第一个方块移到b上:

 然后再将第二个方块移到c上:

 再将b上的第一个方块移到c上:

摆放顺序为a>b,a>c,b>c。在这个过程中目的是将a所有的方块移到c上,但在这期间必须要把a(1)放在b上,可以理解为要将a放到c但a(1)>b是实现目标的过程。 其实分析到此处就可以了,再往下思路容易陷进递归中,出不来。如果这个过程不了解可以去玩一下很容易就明白了,如果不了解过程是很难做出来的。

好现在就可以写代码了

#include<stdio.h>
void Tower_of_Hanoi(int num,char a,char b,char c);
int main(){

}
void Tower_of_Hanoi(int num,char a,char b,char c){

}

创建一个Tower_of_Hanoi函数 ,因为要的是解题步骤所以不需要返回值,传入的参数为num:方块的数量,a,b,c为三个柱子(注:a为开始的柱子,b为过程的柱子,c为结束的柱子),不要理解错,并不是a对应a柱子,b对应b柱子,c对应c柱子!!!这就是为什么我上面要提到过程。

设置退出递归的方法,也就是当只有一个方块时把a>c就好了,如下:

#include<stdio.h>
void Tower_of_Hanoi(int num,char a,char b,char c);
int main(){

}
void Tower_of_Hanoi(int num,char a,char b,char c){
    if (num == 1) {
	printf("%c放到%c", a, c);
}
else {

}
}

如果方块数量大于一,之后不论多少块都将其看成是两块,一个num,一个(num-1)。第一步要将num上的方块(num-1)移到b,如果无法一步实现需要借助c柱子,这时c柱子就为过程的柱子,a为开始的柱子,c为结束的柱子。代码为:

 

#include<stdio.h>
void Tower_of_Hanoi(int num,char a,char b,char c);
int main(){

}
void Tower_of_Hanoi(int num,char a,char b,char c){
    if (num == 1) {
	printf("%c放到%c", a, c);
}
else {
    Tower_of_Hanoi(num - 1, a, c, b);
   
}
}

第二步把num移到c上就是a>c,直接写出来就可以:

#include<stdio.h>
void Tower_of_Hanoi(int num,char a,char b,char c);
int main(){

}
void Tower_of_Hanoi(int num,char a,char b,char c){
    if (num == 1) {
	printf("%c放到%c", a, c);
}
else {
    Tower_of_Hanoi(num - 1, a, c, b);
    printf("%c放到%c\n", a, c);
}
}

第三步把在b柱子上的方块通过a放到c上。代码为:

#include<stdio.h>
void Tower_of_Hanoi(int num,char a,char b,char c);
int main(){

}
void Tower_of_Hanoi(int num,char a,char b,char c){
    if (num == 1) {
	printf("%c放到%c", a, c);
}
else {
    Tower_of_Hanoi(num - 1, a, c, b);
    printf("%c放到%c\n", a, c);
    Tower_of_Hanoi(num - 1, b, a, c);
}
}

至此代码完毕。可以将Tower_of_Hanoi函数放到main函数中运行。

完整代码,其中我自己加了计算运算次数的方法函数,如不需要忽略即可。

#include<stdio.h>
//递归实现汉诺塔问题
void Tower_of_Hanoi(int num, char a, char b, char c);
int Tower_of_Hanoi_number(int number, char a, char b, char c);
int main() {
	int num;
	int number;
	scanf_s("%d", & num);
	Tower_of_Hanoi(num,'a', 'b', 'c');
	number = Tower_of_Hanoi_number(num, 'a', 'b', 'c');
	printf("共执行%d次", number);

}
void Tower_of_Hanoi(int num,char a,char b,char c) {
	
	if (num == 1) {
		printf("%c放到%c\n", a, c);
	}
	else {
		Tower_of_Hanoi(num - 1, a, c, b);
		printf("%c放到%c\n", a, c);
		Tower_of_Hanoi(num - 1, b, a, c);
	}
}
int Tower_of_Hanoi_number(int number, char a, char b, char c) {
	int a1, b1;
	if (number == 1) {
		return 1;
	}
	else {
		a1=Tower_of_Hanoi_number(number - 1, a, c, b);
		
		b1=Tower_of_Hanoi_number(number - 1, b, a, c);

		return a1 + b1 + 1;
	}
}

再写代码的时候不能太过钻牛角尖,尤其是自己还不太熟练的情况下太钻牛角尖会影响自己的思路,想着想着就蒙了,这个问题一开始我就想的很复杂,把num设个四五个然后去找里面的规律,呈指数倍增长的运算搞得我乱七八糟,后来发现其实没必要去算那么多。

而且可以认定为你的Tower_of_Hanoi函数一旦创建不管你写没写完,开没开始写,就将它认定为已经实现了所能完成的任务,这对后面的递归代码编写或许有所帮助,要不然考虑的越多自己的思路越不清晰。

以上是我写这个代码的感觉,也可以是算心得吧,上面的代码变量和函数命名可能不太规范,大胆去写,有bug在改就好了,改bug何尝不是一种学习和练习的放式。

感谢您能看到这里,如果内容和代码有问题欢迎批改指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值