汉诺塔问题的再回顾与再思考(递归算法)

问题:汉诺塔
Problem Description:
汉诺塔(又称河内塔)问题是印度的一个古老的传说。

开天辟地的神勃拉玛在一个庙里留下了三根金刚石的棒A、B和C,A上面套着n个圆的金片,最大的一个在底下,其余一个比一个小,依次叠上去,庙里的众僧不倦地把它们一个个地从A棒搬到C棒上,规定可利用中间的一根B棒作为帮助,但每次只能搬一个,而且大的不能放在小的上面。

僧侣们搬得汗流满面,可惜当n很大时这辈子恐怕就很搬完了。

聪明的你还有计算机帮你完成,你能写一个程序帮助僧侣们完成这辈子的夙愿吗?
Input
输入金片的个数n。这里的n<=10。
Output
输出搬动金片的全过程。格式见样例。
Sample Input

1
2

Sample Output

1
2
3
Move disk 1 from A to B
Move disk 2 from A to C
Move disk 1 from B to C

汉诺塔问题,是函数递归算法中最为经典的案例,其解法的唯一性使其成为了递归算法讲解和练习中的“必考题”。今天,再次重新回顾了一遍汉诺塔问题(竟然搞了辣么久),其中所犯的错误和思路的重新梳理都让我有了非常的大的收获。

题目分析:
本题最重要的思想:

整体思想

首先我们拿到题都会选择使用归纳法,因此我们不妨先带入n=1,也就是只有一个金片的时候,显然,我们只需要将这个金片从A——>C即可(so easy!(●ˇ∀ˇ●))。此时还很难抽取规律,因此我们再带入n=2,也很容易的得出把disk1 A——>B,disk2 A——>C,disk1B——>C,

当n>=3时,想再一一列举已经有些困难了,因此我们从中抽取规律。我们可以利用整体思想,将上面部分的n-1个看作一个整体,第n个单独一个整体,于是移动n个金片的问题变成了移动上面n-1个移动到B,第n个金片移动到C,再把n-1个移动到C的问题,而上面的n-1个金片的每次移动,又可以看作时上面n-2个和第n-1个的分别移动……

这里用到的便是递归(递归中的回溯)算法。系不系有一点凌乱,木关系,再看一边鸭。(@_@;)!

然后说一下程序中的实现,首先是函数,这里我所用到的一共有两个,一个是完成汉诺塔的递归逻辑的函数,另一个是负责每次移动的打印的函数(其实,也可以再递归逻辑中顺便打印粗来,,,多帅哦,小老板d=====( ̄▽ ̄*)b)

我们递归逻辑函数中先是放入了金片的数目(或者说是金片的编号),然后是三根棒(bang1,2,3),这里我是将需要空出的棒放在中间位置(都可以相互调整但要注意在递归函数中移动方向,空出的棒要一一对应)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<stdio.h>
void hanoi(int n,char bang1,char bang2,char bang3);
void move(int n,char bang1,char bang3);
int main()
{
int n;
scanf("%d",&n);

hanoi(n,'A','B','C');
return 0;
}

void hanoi(int n,char bang1,char bang2,char bang3)
{
if(n==1)
{
move(n,bang1,bang3);
}
else
{
hanoi(n-1,bang1,bang3,bang2);
move(n,bang1,bang3);
hanoi(n-1,bang2,bang1,bang3);
}
}
void move(int n,char bang1,char bang2)
{
printf("Move disk %d from %c to %c\n",n,bang1,bang2);
}

最后说一下我为什么又选择使用一个专门的函数去打印每个移动过程,,因为,,直接嵌在递归函数里面非常容易弄错,比如方向等问题。而设立的这个打印函数,只需要考虑他的move方向即可。
总的来嗦,这次的汉诺塔问题回顾,让我更加深刻的理解了递归函数的意义及用法。
( ̄y▽ ̄)╭ Ohohoho…..,,。

坚持原创技术分享,您的支持也将成为我的动力!
-------------本文结束感谢您的阅读-------------
undefined