@@ -127,8 +127,63 @@ def print_num_recursive_revserve(n):
127127不幸的是 python 默认不支持尾递归优化(见延伸阅读),不过一般尾递归我们可以用一个迭代来优化它。
128128
129129
130- # 著名的汉诺塔问题
130+ # 汉诺塔问题
131131
132+ 有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
133+ 但是有两个条件:
134+
135+ - 每次只能移动一个圆盘;
136+ - 大盘不能叠在小盘上面。
137+
138+ > 最早发明这个问题的人是法国数学家爱德华·卢卡斯。
139+ > 传说越南河内某间寺院有三根银棒,上串64个金盘。寺院里的僧侣依照一个古老的预言,以上述规则移动这些盘子;预言说当这些盘子移动完毕,世界就会灭亡。
140+ > 这个传说叫做梵天寺之塔问题(Tower of Brahma puzzle)。但不知道是卢卡斯自创的这个传说,还是他受他人启发。
141+
142+
143+
144+ ![ 五个盘子的汉诺塔问题] ( ./hanoi_tower.png )
145+
146+ 理解这个问题需要我们一些思维上的转换,因为我们正常的思维可能都是从上边最小的盘子开始移动,但是这里我们从移动最底下的盘子开始思考。
147+ 假设我们已经知道了如何移动上边的四个盘子到 B(pole2),现在把最大的盘子从 A -> C 就很简单了。当把最大的盘子移动到
148+ C 之后,只需要把 B 上的 4 个盘子从 B -> C 就行。(这里的 pole1, 2, 3 分别就是 A, B, C 杆)
149+
150+ ![ ] ( ./hanoi_four_disks.png )
151+
152+ 问题是仍要想办法如何移动上边的 4 个盘子,我们可以同样的方式来移动上边的 4 个盘子,这就是一种递归的解法。
153+ 给定 n 个盘子和三个杆分别是 源杆(Source), 目标杆(Destination),和中介杆(Intermediate),我们可以定义如下递归操作:
154+
155+ - 把上边的 n-1 个盘子从 S 移动到 I,借助 D 杆
156+ - 把最底下的盘子从 S 移动到 D
157+ - 把 n-1 个盘子从 I 移动到 D,借助 S
158+
159+ 我们把它转换成代码:
160+
161+ ``` py
162+ def hanoi_move (n , source , dest , intermediate ):
163+ if n >= 1 : # 递归出口,只剩一个盘子
164+ hanoi_move(n- 1 , source, intermediate, dest)
165+ print (" Move %s -> %s " % (source, dest))
166+ hanoi_move(n- 1 , intermediate, dest, source)
167+ hanoi_move(3 , ' A' , ' C' , ' B' )
168+
169+ # 输出,建议你手动模拟下。三个盘子 A(Source), B(intermediate), C(Destination)
170+ """
171+ Move A -> C
172+ Move A -> B
173+ Move C -> B
174+ Move A -> C
175+ Move B -> A
176+ Move B -> C
177+ Move A -> C
178+ """
179+ ```
180+
181+ <center >
182+ ![ 三个盘子的汉诺塔解法] ( ./hanoi.gif )
183+ </center >
184+
185+ 是不是很神奇,但是老实说这个过程仅凭大脑空想是比较难以想象出来的。人的大脑『栈』深度很有限,因为你甚至都没法同时记住超过 8 个以上的
186+ 无意义数字,所以用大脑模拟不如用纸笔来模拟下。(不排除有些聪明的同学能迅速在脑瓜里完成这个过程)
132187
133188# 延伸阅读
134189递归是个非常重要的概念,我们后边的数据结构和算法中还会多次碰到它,我建议你多阅读一些资料加深理解:
@@ -137,6 +192,7 @@ def print_num_recursive_revserve(n):
137192- 《Data Structures and Algorithms in Python》 第 10 章 Recursion
138193- [ 《Python开启尾递归优化!》] ( https://segmentfault.com/a/1190000007641519 )
139194- [ 尾调用优化] ( http://www.ruanyifeng.com/blog/2015/04/tail-call.html )
195+ - [ 汉诺塔] ( https://zh.wikipedia.org/wiki/%E6%B1%89%E8%AF%BA%E5%A1%94 )
140196
141197# 思考题
142198- 你能举出其他一些使用到递归的例子吗?
0 commit comments