带你理解 Hanoi 汉诺塔递归算法
一. 由游戏引发的 Hanoi 问题
汉诺塔是根据一个传说形成的一个问题。汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着 64 片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
二. 一种数学问题
我们将 Hanoi 问题抽象为一种数学问题。首先给出如下三个柱子 A、B、C,其中 A 柱子上有从上到下从小叠到大的 N 个云盘。现要求将A柱子上的圆盘都移动到 C 柱子上,其中,每次移动都必须满足:
- 每次只能移动一个圆盘
- 小圆盘上不能放大圆盘
那么针对这个数学问题,就可以提出相关问题:
- 移动 N 个圆盘最少需要多少次
- 第 M 步移动的是哪个圆盘以及圆盘移动方向
解题:
设总共有 N 个圆盘,Steps表示总移动次数
1.对于问题1
(1)if N == 1
第1次 1号盘 A—->C
Steps = 1 次
(2)if N == 2
第1次 1号盘 A—->B
第2次 2号盘 A—->C
第3次 1号盘 B—->C
Steps = 3 次
(3)if N == 3
第1次 1号盘 A—->C
第2次 2号盘 A—->B
第3次 1号盘 C—->B
第4次 3号盘 A—->C
第5次 1号盘 B—->A
第6次 2号盘 B—->C
第7次 1号盘 A—->C
Steps = 7 次
依次往下推,可以发现这样圆盘个数 N 与移动总次数有这样一个规律
1个圆盘的次数 2的1次方减1
2个圆盘的次数 2的2次方减1
3个圆盘的次数 2的3次方减1
...
...
...
n个圆盘的次数 2的n次方减1
所以能得出一个等式关系 :Steps=2n−1Steps=2n−1Steps=2^n-1
2.对于问题2
我们使用 数学归纳法
来理解 Hanoi 递归算法。对于递归其实就是方法内部调用自己,同时也一定有一个结束点。学习过汇编语言的伙伴都应该知道,每次的递归调用实际上行的是一种栈操作,这个递归调用其实是方法调用栈的过程。每次调用时从主线程开始调用方法并进行不断地压栈和出栈操作。其中,方法的调入就是将方法压人栈中,方法的结束就是方法出栈的过程。这样可以保证方法调用的顺序流,即当函数出现多层嵌套时,需要从外到内一层层把函数压入栈中,最后栈顶的函数先执行结束(最内层的函数先执行结束)后出栈,再倒数第二层的函数执行结束出栈,到最后,第一个进栈的函数调用结束后从栈中弹出回到主线程,并且结束。
栈的特点是:FIFO(先进后出)。比如一个方法自己调用自己,其中一个调用过程也就是进栈过程:A->A(1)->A(2)->A(3)
在A(3)时满足某种条件得以退出, 回到 A(2), A(2)结束回到A(1), 再回到A, 出栈过程:A(3)->A(2)->A(1)->A
那么,我们现在来看 Hanoi 的递归问题,首先来看当前 Hanoi 问题的递归算法的实现
### move_hanoi.py
def move(num,go,to):global ii=i+1print('第{}步--移动 {} 号圆盘:'.format(i,num), 'move',go,'to',to)
def hanoi(num,a,b,c):if num == 1:move(num,a,c)returnhanoi(num-1,a,c,b)move(num,a,c)hanoi(num-1,b,a,c)hanoi_move(5,'A','B','C')
i=0
输出效果如下
看起来是不是很简单?当时一直都不能懂为什么就是这样的递归,实际上再听老师多次提起后,感觉像是懵懵懂懂假装懂了,具体懂了没懂,还需要试试探讨一番。通过证明可能是很好的办法。
为了证明这中递归算法的合理性,可以采用 数学中归纳法
来理解。对于递归算法问题也不要妄想一开始就追踪整个递归的全程调用。在知乎上有很多非常形象的描述。实际上,如果是对于少于三个盘的 Hanoi 移动来说,其实很好理解。但当数目越来越多时,把这个问题展开来想就变得复杂了,这也是为什么我们需要从层与层之间的交接来理解,而不是展开整个递归。
现在讨论,当只需要移动一个圆盘时,此时 N = 1
此时只需移动1次,即将第1个圆盘从A移动到C
步骤 圆盘 柱子移动方向
1 1 A -> C
当移动两个盘子,此时 N = 2
步骤 圆盘 柱子移动方向
1 1 A -> B
2 2 A -> C
3 1 B -> C
当移动三个圆盘时,此时N = 3
步骤 圆盘 柱子移动方向
1 1 A -> C
2 2 A -> B
3 1 C -> B
4 3 A -> C
5 1 B -> A
6 2 B -> C
7 1 A -> C
根据上面的移动情况,我们总结出圆盘移动的规律:
- 在移动记录中,当盘子的编号和盘子数量相同的时候他们的步骤都是从A移动到C
- 其他步骤对等
再观察第3个案例中的第 1-3 步 和 第 5-7步
第 1-3 步:目的是从 A 移动到 B。如果我们把 B 当作终点, 那么这里的第 1-3 步理解起来和移动2个圆盘的三个步骤完全相同
步骤 圆盘 柱子移动方向 B、C 互换 1 1 A -> C (A -> B) 2 2 A -> B (A -> C) 3 1 C -> B (B -> C)即此时相当于 (XCHG B,C),将 B、C 进行了互换
第 5-7 步:目的是从 B 移动到 C。如果我们把 C 当作终点, 那么这里的 5-7 步理解起来和移动2个圆盘的三个步骤完全相同
步骤 圆盘 柱子移动方向 B、A 互换 5 1 B -> A (A -> B) 6 2 B -> C (A -> C) 7 1 A -> C (B -> C)即此时相当于 (XCHG B,A),将 B、A 进行了互换
那么,我们将以上得到的规律可以总结为
- 1.只有一个圆盘,Steps=1, 从 A 移动到 C 即结束
- 2.当有 N 个盘,Steps=2^n-1 为奇数,中间都是动作都是从 A 移动到 C
- 3.中间动作之上都可以认为是: 从 A 移动到 B
- 4.中间动作之下都可以认为是: 从 B 移动到 C
我们用伪代码表示以上规律
Function MOVE(N,A,B,C)IF N ==1 THENPrint A;"TO",CELSE CALL MOVE(N-1,A,C,B);//MOVE(N,A,B,C)中 B、C 互换,N=N-1Print A;"TO",CCALL MOVE(N-1,B,A,C);//MOVE(N,A,B,C)中 B、A 互换,N=N-1END IF
这就是对 Hanoi 递归算法的归纳过程
资料引用:
- 汉若塔互动百科
- 函数调用栈 剖析+图解
带你理解 Hanoi 汉诺塔递归算法相关推荐
- 理解 Hanoi 汉诺塔非递归算法
汉诺塔介绍: 汉诺塔(港台:河内塔)是根据一个传说形成的数学问题: 最早发明这个问题的人是法国数学家爱德华·卢卡斯. 传说越南河内某间寺院有三根银棒,上串 64 个金盘.寺院里的僧侣依照一个古老的预言 ...
- 递归算法以及Hanoi(汉诺)塔问题及其详细解释
递归在算法中是非常重要的,可以说几乎所有的循环算法都可以用递归来实现,这足以体现递归的重要性,利用递归的条件一般为一下: 定义是递归的 像有些数学函数就是递归定义的,例如大家熟悉的阶层函数: 2.利用 ...
- python汉诺塔_汉诺塔递归算法/搬金盘的婆罗门 - Python实现
汉诺塔递归算法/搬金盘的婆罗门 - Python实现 版权声明 本文节选自作者本人的图书<Python编程基础及应用>,高等教育出版社.本文可以在互联网上自由转载,但必须:注明出处(作者: ...
- 汉诺塔递归算法/搬金盘的婆罗门 - Python实现
汉诺塔递归算法/搬金盘的婆罗门 - Python实现 本文引用自作者编写的下述图书; 本文允许以个人学习.教学等目的引用.讲授或转载,但需要注明原作者"海洋饼干叔 叔":本文不允许 ...
- c语言递归求塔移动次数,【C语言】Hanoi(汉诺)塔问题,求移动盘子的步骤(递归法)...
所有的循环算法都可以用递归实现,反之不成立,这足以证明递归的重要性! Hanoi(汉诺)塔问题.古代有一个焚塔,塔内有3个座A,B,C,开始时A座上有64个盘子,盘子大小不等,大的在上,小的在下,有一 ...
- C++Tower of Hanoi汉诺塔的实现算法(附完整源码)
C++Tower of Hanoi汉诺塔的实现算法 C++Tower of Hanoi汉诺塔的实现算法完整源码(定义,实现,main函数测试) C++Tower of Hanoi汉诺塔的实现算法完整源 ...
- 汉诺塔递归算法进阶_进阶python 1递归
汉诺塔递归算法进阶 When something is specified in terms of itself, it is called recursion. The recursion give ...
- Hanoi(汉诺)塔问题
问题描述: Hanoi(汉诺)塔问题.古代有一个梵塔,塔内有3个座A,B,C,开始时A座有n个盘子,盘子大小不等,大的在下,小的在上.有一个老和尚想把这n个盘子,从A座移动到C座,但是每次只允许移动一 ...
- C语言---移盘子----Hanoi(汉诺)塔问题,显示移动盘子的步骤
C语言-移盘子----Hanoi(汉诺)塔问题,显示移动盘子的步骤 在学习递归的过程中,Hanoi(汉诺)塔问题是避开不了的,很多新手在这儿一脸懵. 我们先简单介绍一些Hanoi(汉诺)塔问题到底是个 ...
- 汉诺塔-递归算法深入理解
汉诺塔算法就3个步骤: 第一,把a上的n-1个盘通过c移动到b: 第二,把a上的最下面的盘移到c: 第三,因为n-1个盘全在b上了. 所以把b当做a重复以上步骤就好了.不过,思考过程还是很痛苦的,难以 ...
最新文章
- 查看idea的错误日志信息
- VTK:网格之BoundaryEdges
- 【HDOJ】1196 Lowest Bit
- Docker设置HTTP代理
- PhpStorm配置Xdebug调试PHP程序
- Idea中搭建Resin运行环境(Mac)
- phppage类封装分页功能_PHP封装的page分页类定义与用法完整示例
- laravel 错误与日志
- linux bind mysql_linux下安装mysql
- JS获取地址栏参数的方法
- 常用的HTTP头部字段的基本含义(转)
- Xcode6无法安装VVDocumenter插件的解决方法
- 电子科技大学第九届ACM趣味程序设计竞赛(热身赛)题解
- unity3d 绘制小地图_Unity3D —— 小地图制作插件NJG MiniMap
- 联想Y7000装双系统win10+Ubuntu16.04后在Ubuntu上Wifi被禁用的解决办法
- (PTA)7-5 查询水果价格 (15分)
- 怎么更改锁定计算机背景图片,电脑锁屏背景图片如何更改
- 桌面、平板、手机和机器人操作系统(ROS)市场占有率数据和趋势分享(附引用2019版)
- 东芝推出新型低触发LED电流光继电器,满足电池供电设备的低功耗需求
- 用HTML制作一个注册界面