递归——自己调用自己(下)
递归——自己调用自己
-
汉诺塔问题
1:汉诺塔问题描述:
汉诺塔(又称河内塔)问题来源于印度一个古老传说的传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。当婆罗门完成这项工作的时候,世界将会毁灭。
2:抽象成数学问题
(1):第一个问题:我们需要移动多少次原盘呢?世界会在什么时候毁灭呢?

我们以3个盘子(1,2,3)为例,有三根柱子A,B,C,现在我们要把所有的盘子按规则移动到柱子C,具体步骤如下:
第1步:A1——>C1
第2步:A2——>B2
第3步:C1——>B1
第4步:A3——>C3//最大的盘子1放到柱子C
第5步:B1——>A1
第6步:B2——>C2//次大的盘子2放到柱子C
第7步:A1——>C1//最小的盘子3放到柱子C
当四个盘子的时候,我们得到需要15次,依次类推,我们很容易发现规律,盘子移动次数m=2^n-1(盘子数n),那上则故事中世界将在什么时候毁灭呢?假设婆罗门1秒完成一次盘子移动,世界将会在2^64-1秒,即约等于6000亿年!
(2):第二个问题:盘子具体时如何移动的?
当盘子数量较少时,我们能够很容易自己写出流程(如上),但当盘子数量足够多时呢?
我们使用递归解决此问题,最简单时候即有两个盘子1、2,移动步骤如下:
第1步:A1——>B1
第2步:A2——>C2
第3步:B1——>C1
所以实现这个算法可以简单分为三个步骤:
(1)把n-1个盘子由A 移到 B;
(2)把第n个盘子由 A移到 C;
(3)把n-1个盘子由B 移到 C;
3:代码编写
C#
private static int sum = 0;
static void HanoiTower(int num, string deti_A, string deti_B, string desti_C)
{
if (num == 1)
{
Console.WriteLine("第{0}次移动盘子{1}:{2}——>{3}", ++sum, num, deti_A, desti_C);//剩余一个盘子时,直接将盘子移动:A——>C
}
else
{
HanoiTower(num - 1, deti_A, deti_B, desti_C);//把n-1个盘子由A 移到 B(柱子C充当转换站)
Console.WriteLine("第{0}次移动盘子{1}:{2}——>{3}", ++sum, num, deti_A, desti_C);//把第n个盘子由 A移到 C
HanoiTower(num - 1, deti_B, desti_C, deti_A);//把n-1个盘子由B 移到 C(柱子A充当转换站)
}
}
VB.NET
Private sum As Integer = 0
Sub HanoiTower(num As String, dist_A As String, dist_B As String, dist_C As String)
If (num = 1) Then
sum += 1
Console.WriteLine("第{0}次移动盘子{1}:{2}——>{3}", sum, num, dist_A, dist_B)
Else
HanoiTower(num - 1, dist_A, dist_C, dist_B) '把n-1个盘子由A 移到 B(柱子C作为转换站)
sum += 1
Console.WriteLine("第{0}次移动盘子{1}:{2}——>{3}", sum, num, dist_A, dist_C) '把第n个盘子由 A移到 C
HanoiTower(num - 1, dist_A, dist_C, dist_B) '把n-1个盘子由B 移到 C(柱子B作为转换站)
End If
End Sub
效果如下:


浙公网安备 33010602011771号