vb汉诺塔的递归算法与解析
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
汉诺塔的递归算法与解析
从左到右 A B C 柱大盘子
在下, 小盘子在上, 借助B柱将
所有盘子从A柱移动到C柱, 期
间只有一个原则: 大盘子只能
在小盘子的下面.
如果有3个盘子, 大中小号, 越小的越在上面, 从上面给盘子按顺序编号1(小),2(中),3(大), 后面的原理解析引用这里的编号.
小时候玩过这个游戏, 基本上玩到第7个,第8个就很没有耐心玩了,并且操作的动作都几乎相同觉得无聊. 后来学习编程, 认识到递归, 用递归解决汉诺塔的算法也是我除了简单的排序算法后学习到的第一种算法.
至于递归,简单来说就是方法内部自己调用自己, 同时也一定有一个结束点. 如果对方法调用栈了解的话,其实是很容易理解方法的调用过程的, 就是从主线程开始调用方法进行不停的压栈和出栈操作. 方法的调入就是将方法压入栈中, 方法的结束就是方法出栈的过程, 这样保证了方法调用的顺序流. 如果跟踪递归的调用情况会发现也是如此, 到最后一定是这个方法最后从栈中弹出回到主线程, 并且结束.
栈的特点:先进后出。比如一个方法 A 自己调用自己, 我用编号区分一下进栈过程:A -> A(1) -> A(2) -> A(3)
在A(3)时满足某种条件得以退出, 回到A(2), A(2)结束回到A(1), 再回到A, 出栈过程:A(3) -> A(2) -> A(1) -> A
对于递归,还有一个形象的认识,就是我小时候家里有一个柜子, 柜子两端都是玻璃, 头伸进柜子看一面镜子,会看到镜子里还有镜子, 然后镜子里还有镜子, 但和递归的特点不同的是这镜子的反射是没有尽头的, 只要眼睛一直能看到底的话.
了解完递归后, 再回头来看如何用递归的方式解决汉诺塔的问题.
案例 1 - 假设只有一个盘子的时候, 盘子数量N=1
只有一个步骤将第1个盘子从A移动到C, 为了对比方便我这样来描述这个步骤:
步骤盘子编号从柱子移动移动到柱子
1 1 A C
案例 2 - 如果有两个盘子, 盘子数量N = 2
步骤盘子编号从柱子移动移动到柱子
1 1 A B
2 2 A C
3 1 B C
案例 3 - 如果有三个盘子, 盘子数量N = 3
步骤盘子编号从柱子移动移动到柱子
1 1 A C
2 2A B
3 1 C B
4 3 A C
5 1 B A
6 2 B C
7 1 A C
如何找出盘子移动的规律?
我们要做的最重要的一件事情就是永远要把最底下的一个盘子从 A 移动到C
看看上面从1个盘子的移动到3个盘子的移动, 在移动记录中,当盘子的编号和盘子数量相同的时候他们的步骤都是从A移动到C (看加粗的部分),其它的步骤对等.
再观察第3个案例中的第1-3 步和第5-7步
第1-3 步目的是从 A 移动到 B 如果我们把 B 当作终点, 那么这里的第1-3 步理解起来和第2个案例的三个步骤完全相同, 都是通过一个柱子来移动,和第2个案例比起来在后面加括号来表示
1 1 A C ( A -> B)
2 2A B ( A -> C)
3 1 C B ( B -> C)
总结:将盘子B变成C即可.
第5-7 步目的是从 B 移动到 C 如果我们把 C 当作终点, 那么这里的5-7 步理解起来和上面也是一样的, 和第2个案例的三个步骤也完全相同.和第2个案例比起来就是:
5 1 B A ( A -> B)
6 2 B C ( A- > C)
7 1 A C ( B -> C)
总结: 将盘子B变成A即可
根据这个演示可以明确几点规律:
1. 当盘子只有一个的时候,只有一个动作从A 移动到C 即结束.
2. 当有N个盘子的时候, 中间的动作都是从A 移动到C, 那么表示最下面的第N个盘子移动完毕
3. 中间动作之上都可以认为是: 从A 移动到B
4. 中间动作之下都可以认为是: 从B 移动到C
2,3,4 可以表示为
1 1 A B
2 2 A C
3 1 B C
这种结构一直在重复进行,就有了以下代码:
Sub move1(n, a, b, c)
If n = 1 Then
Print a;"->"; c
Else
Call move1(n - 1, a, c, b)
Print a;"->"; c
Call move1(n - 1, b, a, c)
End If
End Sub
Private Sub Form_Click()
n = InputBox("请输入要移动的块数:") Call move1(n, "a", "b", "c")
End Sub