我相信很多朋友都知道汉诺塔问题,也有不少看过了它的程序实现,但我想有不少人不懂它是什么意思,为什么那几行程序就把汉诺塔问题给解了呢?
先啰嗦一会儿。解释一下。。。
看看汉诺塔的由来 (从百度百科中摘来的)
汉诺塔是源自印度神话里的玩具。
上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上安大小顺序摞着64片黄金圆盘。
上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今还在一刻不停地搬动着圆盘。
汉诺塔与宇宙寿命 如果移动一个圆盘需要1秒钟的话,等到64个圆盘全部重新落在一起,宇宙被毁灭是什么时候呢?
让我们来考虑一下64个圆盘重新摞好需要移动多少次吧。1个的时候当然是1次,2个的时候是3次,3个的时候就用了7次......这实在是太累了
因此让我们逻辑性的思考一下吧。
4个的时候能够移动最大的4盘时如图所示。
到此为止用了7次。
接下来如下图时用1次,在上面再放上3个圆盘时还要用7次(把3个圆盘重新放在一起需要的次数)。
因此,4个的时候是
“3个圆盘重新摞在一起的次数”+1次+“3个圆盘重新摞在一起需要的次数”
=2x“3个圆盘重新摞在一起的次数”+1次
=15次。
那么,n个的时候是
2x“(n-1)个圆盘重新摞在一起的次数”+1次。
由于1 个的时候是1次,结果n个的时候为(2的n次方减1)次。
1个圆盘的时候 2的1次方减1
2个圆盘的时候 2的2次方减1
3个圆盘的时候 2的3次方减1
4个圆盘的时候 2的4次方减1
5个圆盘的时候 2的5次方减1
........
n个圆盘的时候 2的n次方减1
也就是说,n=64的时候是(2的64次方减1)次。
因此,如果移动一个圆盘需要1秒的话,
宇宙的寿命=2的64次方减1(秒)
2的64次方减1到底有多大呢?动动计算器,答案是一个二十位的数字:
18446744073709551615!
用一年=60秒x60分x24小时x365天来算的话,大约有5800亿年吧。
据说,现在的宇宙年龄大约是150亿年,还差得远呢。
汉诺塔问题在数学界有很高的研究价值,
而且至今还在被一些数学家们所研究,
也是我们所喜欢玩的一种益智游戏,
它可以帮助开发智力,激发我们的思维。
汉诺塔的C语言实现
#include<stdio.h>
void move(char x,char y)
{
printf("%c-->%c\n",x,y);
}
void hanoi(int n,char one ,char two,char three)
{
if(n==1) move(one,three);
else
{
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
}
}
main()
{
int m;
printf("input the number of disks:");
scanf("%d",&m);
printf("the step to moving %3d diskes:\n",m);
hanoi(m,'A','B','C');
}
看到这个程序 ,大家最难理解的就是下面两句:
hanoi(n-1,one,three,two);
hanoi(n-1,two,one,three);
我们知道它用了递归,第一句把第一个位置的盘移到第二个位置,第二句再把第二个移到第三个位置。 但为什么这样就可以递归出答案呢?
这个可以用二叉树的中序遍历来解释。下面看一个图估计你就会知道了。
这是一个递归的图解,根结点是第一次进入hanoi函数,第一个参数3只要大于1就往下推,第二个参数是指要移动的盘的原始位置(最上面的那个),第四个参数是指要移动到的目的位置,第三个参数在函数里面没什么用,只是为了下一次递归时准备的一个参数。这个图是按照程序画出来的,上面的节点个数就是调用hanoi函数的次数。现在我们来中序遍历这棵二叉树。
假设:开始时a,b,c三个盘都放在one上,从a到c依次增大,就是说c放在最下面,a在最上面,->表示移动。
节点4:a->three
节点2:b->two
节点5:a->two
节点1:c->three
节点6:a->one
节点3:b->three
节点7:a->three
完成。。。
假设有4个盘呢?那也是一样的道理可以推出。这时就有15个节点,就是说要移动15次。那有n个盘呢?2的n次方减1……
从这边可以看出,递归和二叉树有很多联系。从递归转化成非递归时,一般都可以用二叉树实现。怎么实现呢,可以看一下我之前的一篇日志。。。
分享到:
相关推荐
汉诺塔和二叉树是计算机科学中两个重要的概念,它们在解决问题和数据结构设计上具有深远的影响。这里我们将深入探讨这两个主题,并结合程序演示来理解它们的工作原理。 首先,让我们来谈谈汉诺塔(Hanoi Tower)...
汉诺塔演示程序结合了二叉树的演示动画,为学习和理解这两种计算机科学基础知识提供了一个生动直观的方式。首先,我们来深入探讨一下汉诺塔问题及其解决方案。 汉诺塔是一个经典的递归问题,由三个柱子和一堆大小...
2. **虚拟指针**:使用一个虚拟指针来指向汉诺塔状态树中的当前节点,与二叉树遍历中的实际指针对应,这样可以帮助学生直观地理解二者之间的关系。 3. **多维度比较**:从逻辑结构、求解步骤、代码实现、栈存储结构...
利用二叉树法,实现汉诺塔的非递归,根据盘子数和第几步,快速得到每一步移动的操作,速度快,省内存。已经经过调试运行,算法思想参见http://wenku.baidu.com/view/81a05a80e53a580216fcfeba.html,本人源码是根据...
本文将详细介绍几种经典的数据结构问题及其实现,包括汉诺塔问题、逆阵问题、硬币情况、二叉树的实现以及图的遍历。通过这些案例,我们将深入理解数据结构的精妙所在及其在解决实际问题中的应用。 首先,汉诺塔问题...
C++数据结构经典例程,八皇后,汉诺塔等
本篇文章将探讨一种新的汉诺塔问题解模型,通过构建一个与汉诺塔问题完全等价的满二叉树模型来寻找每个圆盘移动的规律,并基于此规律开发一个高效的非递归算法。 #### 汉诺塔问题模型 ##### 汉诺塔问题描述 汉诺...
数据结构用栈实现汉诺塔,用递归给你讲吧,先想这个棵树Tn,先把最下面的n要搬走,就得把上面的n-1个先搬走,这个n-1个也形成一个树T(n-1),然后又把这n-1个搬到n上面又形成一个T(n-1)的树,这个你就可以画出来...
汉诺塔(Hanoi Tower)算法,又称为巴黎塔问题,是计算机科学中一个经典的递归问题。这个算法源于一个古老的印度传说,涉及到三个柱子和一堆大小不一的圆盘。目标是将所有圆盘从一个柱子移动到另一个柱子,每次只能...
汉诺塔游戏是一个经典的计算机科学问题,源自印度的古老传说,目标是将所有盘子从一个柱子(称为起始柱)移动到另一个柱子(称为目标柱),但每次只能移动一个盘子,并且任何时候大盘子都不能位于小盘子之上。...
下面我们将详细探讨非递归实现汉诺塔的两种常见方法:基于栈的迭代和二叉树实现。 ### 基于栈的迭代实现 在这个实现中,我们创建两个栈,分别代表辅助柱子和目标柱子。主栈用于存储当前操作的状态。我们维护三个...
本文实例讲述了C++基于递归算法解决汉诺塔问题与树的遍历功能。分享给大家供大家参考,具体如下: 递归是把问题转化为规模缩小的同类问题,然后迭代调用函数(或过程)求得问题的解。递归函数就是直接或间接调用自身...
在学习汉诺塔问题时,可以深入理解递归的思想,掌握如何设计和分析递归函数,这对于进一步学习其他复杂的算法如快速排序、二叉树遍历等至关重要。同时,它也能帮助我们锻炼逻辑思维和问题解决能力,这对任何IT从业者...
- **汉诺塔**:汉诺塔问题是一个经典的递归问题,通过将盘子从一根柱子移动到另一根柱子,遵循每次只能移动一个盘子且大盘子不能位于小盘子之上的规则。 - **排序算法**:包括冒泡排序、选择排序、插入排序、快速...
这里我们关注的几个数据结构例程涵盖了多种重要概念,包括汉诺塔问题、赫夫曼编码、静态查找表、链表操作、图的深度优先遍历以及希尔排序。下面将对这些知识点进行详细解释。 1. **汉诺塔**:这是一个经典的递归...
学习汉诺塔问题有助于理解递归的概念,这对于学习其他编程语言和算法如快速排序、二叉树遍历等都非常有帮助。同时,它也提供了一个直观的视角来观察如何通过函数调用栈处理复杂问题。在实际开发中,这种解决问题的...
### hanoi(汉诺塔)问题的非递归实现 #### 概述 汉诺塔问题是一种经典的递归算法示例,在计算机科学领域被广泛应用于教授递归思想和技术。传统解决汉诺塔问题的方法通常采用递归算法,尽管这种方法结构清晰易懂,...
汉诺塔(Hanoi Tower)是一个经典的递归问题,源于19世纪法国数学家爱德华·卢卡斯提出的一个智力游戏。这个问题涉及到三个柱子和一堆大小不一的圆盘,目标是将所有圆盘从一个柱子移动到另一个柱子,每次只能移动一...
汉诺塔问题是一个经典的递归问题,源自古印度的一个传说,它涉及到三个柱子和一组大小不等的圆盘。目标是将所有盘子从初始柱子(通常为A柱)移动到目标柱子(通常为C柱),遵循以下三个规则: 1. 每次只能移动一个...
解决汉诺塔问题的关键在于使用递归策略:首先将上层的n-1个盘子借助中间柱子B移到目标柱子C,然后将剩余的大盘子直接移到C,最后再把之前放在B上的n-1个盘子借助A移到C。 多线程是现代计算机编程中的一个重要概念,...