汉诺塔问题非递归算法详解
汉诺塔问题的非递归算法设计及可视化实现
![汉诺塔问题的非递归算法设计及可视化实现](https://img.taocdn.com/s3/m/68117158ff4733687e21af45b307e87101f6f877.png)
汉诺塔问题的非递归算法设计及可视化实现彭伟【摘要】This essay introduces the classic recursive algorithm of the famous Hanoi,and then carries out further analysis and study on the algorithm based on the binary recursive tree to get a non-recursive solution without using the stack technology.Finally,designing procedures of development environment are visualized in NET,using recursive and non-recursive algorithm respectively to solve Hanoi of specified scale,with the moving effects of disc being dynamically simulated.%讨论了汉诺塔问题的经典递归算法,并基于二叉递归树对算法进行研究,得出了一种不使用堆栈技术的非递归解法,最后在.NET可视化开发环境下设计程序,分别用递归与非递归算法求解指定规模的汉诺塔问题,动态模拟了求解过程中盘片的移动效果。
【期刊名称】《武汉船舶职业技术学院学报》【年(卷),期】2011(010)006【总页数】6页(P55-59,72)【关键词】汉诺塔;二叉树;递归,非递归;可视化;模拟【作者】彭伟【作者单位】武汉城市职业学院,湖北武汉430064【正文语种】中文【中图分类】TP301汉诺塔游戏最早于19世纪出现在欧洲,它展示了一项正在婆罗门寺庙进行的任务:在创世之初,牧师被授予一个铜盘,上面有3根钻石针,在第1根针上叠放着64个碟片,每一个都比它下面的稍小一些,这位牧师被安排了一项任务,那就是将所有的碟片从第1根针移到第3根针,但要遵循的规则是:一次只能移动一个碟片,并且不允许将任何一个碟片放在比它小的碟片上面。
汉诺塔问题
![汉诺塔问题](https://img.taocdn.com/s3/m/3f11771031b765ce0508146c.png)
盐城工学院C++课程设计二级学院:信息学院班级:姓名:学号:指导老师:1.报告简介1.1 汉诺塔问题简介在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。
印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔(如下图)。
不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必在大片上面。
当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,梵塔、庙宇和众生都将同归于尽。
故汉诺塔问题又被称为“世界末日问题。
”图1-11.2 问题思想解决为满足题目中盘子的移动问题,必须遵循的条件是:一次仅能移动一个盘,且不允许大盘放在小盘的上面。
设要解决的汉诺塔共有N个圆盘,对A杆上的全部N个圆盘从小到大顺序编号,最小的圆盘为1号,次之为2号,依次类推,则最下面的圆盘的编号为N。
第一步:先将问题简化。
假设A杆上只有一个圆盘,即汉诺塔只有一层N,则只要将1号盘从A杆上移到B杆上即可。
第二步:对于一个有N(N>1)个圆盘的汉诺塔,将N个圆盘分成两部分:“上面的N-1个圆盘”看成一个整体,为了解决N个圆盘的汉诺塔,可以按下面图示的方式进行操作:(1)将A杆上面的N-1个盘子,借助B杆,移到C杆上;图1-2(2)将A杆上剩余的N号盘子移到B杆上;图1-3(3)将C杆上的N-1个盘子,借助A杆,移到B杆上。
图 1-41.3 预期目标运行程序后,首先显示:图 1-5选择 1 后,要求输入盘子的数目,即N输入后,显示递归调用时盘子移动的过程图 1-6继续选择 2 ,要求输入盘子的数目,即P输入后,显示非递归调用时盘子移动过程。
图 1-72.需求分析编写汉诺塔程序用到的知识有:符号常量的定义,循环语句,函数,栈与应用;2.1 符号常量的定义常量就是在程序运行过程中其值不发生变化的量。
汉诺塔问题求解思路
![汉诺塔问题求解思路](https://img.taocdn.com/s3/m/6271e7004531b90d6c85ec3a87c24028915f852c.png)
汉诺塔问题求解思路汉诺塔问题是⼀个经典的问题。
汉诺塔(Hanoi Tower),⼜称河内塔,源于印度⼀个古⽼传说。
⼤梵天创造世界的时候做了三根⾦刚⽯柱⼦,在⼀根柱⼦上从下往上按照⼤⼩顺序摞着64⽚黄⾦圆盘。
⼤梵天命令婆罗门把圆盘从下⾯开始按⼤⼩顺序重新摆放在另⼀根柱⼦上。
并且规定,任何时候,在⼩圆盘上都不能放⼤圆盘,且在三根柱⼦之间⼀次只能移动⼀个圆盘。
问应该如何操作?分析如果是初次接触类似的问题,乍看之下肯定会感觉⽆从下⼿。
要把64个圆盘从a柱⼦移动到c柱⼦上,第⼀步应该怎么做?虽然可以肯定,第⼀步唯⼀的选择是移动a最上⾯的那个圆盘,但是应该将其移到b还是c呢?很难确定。
因为接下来的第⼆步、第三步……直到最后⼀步,看起来都是很难确定的。
能⽴即确定的是最后⼀步:最后⼀步的盘⼦肯定也是a最上⾯那个圆盘,并且是由a或b移动到c——此前已经将63个圆盘移动到了c上。
也许你会说,管他呢,先随便试着移动⼀下好了。
如果你这么做,你会发现,接下来你会⾯临越来越多类似的选择,对每⼀个选择都“试”⼀下的话,你会偏离正确的道路越来越远,直到你发现你接下来⽆法进⾏为⽌。
如果将这个问题的盘⼦数量减为10个或更少,就不会有太⼤的问题了。
但盘⼦数量为64的话,你⼀共需要移动约1800亿亿步(18,446,744,073,709,551,615),才能最终完成整个过程。
这是⼀个天⽂数字,没有⼈能够在有⽣之年通过⼿动的⽅式来完成它。
即使借助于计算机,假设计算机每秒能够移动100万步,那么约需要18万亿秒,即58万年。
将计算机的速度再提⾼1000倍,即每秒10亿步,也需要584年才能够完成。
注:在我的笔记本电脑上,每秒⼤约能够移动6~8百万步。
虽然64个盘⼦超出了⼈⼒和现代计算机的能⼒,但⾄少对于计算机来说,这不是⼀个⽆法完成的任务,因为与我们⼈类不同,计算机的能⼒在不断提⾼。
分解问题⼀股脑地考虑每⼀步如何移动很困难,我们可以换个思路。
python汉诺塔非递归算法
![python汉诺塔非递归算法](https://img.taocdn.com/s3/m/9732ea87d4bbfd0a79563c1ec5da50e2534dd169.png)
python汉诺塔非递归算法如何使用Python编写非递归的汉诺塔算法首先,让我们回顾一下汉诺塔问题的背景。
汉诺塔是一个经典的数学问题,涉及到递归和栈的使用。
问题的目标是将一组不同大小的圆盘从一个柱子移动到另一个柱子,其中有三个柱子可供选择。
在移动过程中,您必须遵守以下规则:1. 您只能移动一个圆盘,并且只能将较小的圆盘放在较大的圆盘上。
2. 您只能在三个柱子之间移动圆盘。
3. 将所有圆盘从一个柱子移动到另一个柱子上是成功的。
使用递归算法可以很容易地解决这个问题。
然而,递归算法在处理大量圆盘时可能会导致递归深度过大,从而消耗大量的内存和计算时间。
因此,我们需要采用非递归的方法来解决这个问题。
接下来,让我们一步一步地介绍如何使用Python编写非递归的汉诺塔算法:步骤1: 定义一个Stack类首先,我们需要定义一个Stack类来模拟栈的行为。
在Python中,可以使用列表来实现这个类。
我们可以使用列表的append()方法将元素添加到栈顶,使用pop()方法从栈顶取出元素,使用isEmpty()方法检查栈是否为空,以及使用size()方法获取栈的大小。
下面是Stack类的代码实现:class Stack:def __init__(self):self.items = []def isEmpty(self):return len(self.items) == 0def push(self, item):self.items.append(item)def pop(self):return self.items.pop()def size(self):return len(self.items)步骤2: 定义一个非递归的汉诺塔函数接下来,我们需要定义一个非递归的汉诺塔函数。
该函数的输入参数包括圆盘的数量、起始柱子、目标柱子和辅助柱子。
函数的实现思路如下:- 首先,将所有的圆盘按照倒序从起始柱子压入起始栈。
采用递归和非递归方法求解hannol问题
![采用递归和非递归方法求解hannol问题](https://img.taocdn.com/s3/m/b8c932fc970590c69ec3d5bbfd0a79563d1ed477.png)
采用递归和非递归方法求解hannol问题汉诺塔问题是数学中的经典问题之一,也被认为是计算机科学中的经典问题。
它的解法可以使用递归或非递归的方法。
在本文中,我们将介绍并比较这两种解法。
汉诺塔问题的描述是:有三根柱子,A、B、C,初始时,A柱子上有n个盘子,这些盘子从小到大按顺序堆叠在一起。
现在需要将这n 个盘子从A柱子移动到C柱子上,期间可以借助B柱子。
移动盘子有以下几个规则:1.每次只能移动一个盘子;2.盘子只能从大盘子移到小盘子上;3.在移动过程中,可以借助柱子进行中转。
接下来,我们将先介绍递归解法。
递归解法:对于n个盘子,我们可以将问题分解为以下三个步骤:1.将n-1个盘子从A柱子移动到B柱子;2.将第n个盘子从A柱子移动到C柱子;3.将n-1个盘子从B柱子移动到C柱子。
递归解法的代码如下:```pythondef hanoi(n, A, B, C):if n == 1:print("Move disk %d from %s to %s" % (n, A, C)) else:hanoi(n-1, A, C, B)print("Move disk %d from %s to %s" % (n, A, C)) hanoi(n-1, B, A, C)```在这个递归函数中,n表示盘子的数量,A、B、C表示三根柱子。
当n为1时,直接将第一个盘子从A柱子移动到C柱子;否则,先将n-1个盘子从A柱子移动到B柱子,然后将第n个盘子从A柱子移动到C柱子,最后将n-1个盘子从B柱子移动到C柱子。
递归的过程中,会不断地将问题分解为子问题,直到子问题规模减小到1。
下面是一个具体的例子,假设有3个盘子,初始时都在A柱子上:```pythonhanoi(3, 'A', 'B', 'C')```输出结果为:```Move disk 1 from A to CMove disk 2 from A to BMove disk 1 from C to BMove disk 3 from A to CMove disk 1 from B to AMove disk 2 from B to CMove disk 1 from A to C```如上所示,递归解法将问题分解为子问题,然后逐步解决子问题,最后得到整体的解。
汉诺塔问题非递归算法c语言
![汉诺塔问题非递归算法c语言](https://img.taocdn.com/s3/m/c161eeb1900ef12d2af90242a8956bec0875a562.png)
汉诺塔问题非递归算法c语言汉诺塔问题是一个经典的数学问题,也是一个常见的编程练习题。
在这个问题中,有三根柱子和一些圆盘,圆盘的大小不一,从小到大依次叠放在一根柱子上。
目标是将所有的圆盘从一根柱子移动到另一根柱子,移动过程中要保证大的圆盘在小的圆盘上面。
同时,每次只能移动一个圆盘,且不能把一个大的圆盘放在一个小的圆盘上面。
在解决汉诺塔问题时,通常采用递归算法。
但是递归算法的效率并不高,因为每次递归都会产生额外的函数调用,增加了系统的开销。
因此,我们可以通过非递归的方式来解决汉诺塔问题,提高算法的效率。
以下是一个用C语言实现的汉诺塔问题的非递归算法:```c#include <stdio.h>#include <stdlib.h>typedef struct {int n;char start, end, temp;} StackNode;typedef struct {StackNode data[100];int top;} Stack;void push(Stack *s, StackNode node) {s->data[s->top++] = node;}StackNode pop(Stack *s) {return s->data[--s->top];}void hanoi(int n, char start, char end, char temp) {Stack s;s.top = 0;StackNode node;node.n = n;node.start = start;node.end = end;node.temp = temp;push(&s, node);while (s.top > 0) {node = pop(&s);if (node.n == 1) {printf("Move disk 1 from %c to %c\n", node.start, node.end); } else {StackNode node1, node2, node3;node1.n = node.n - 1;node1.start = node.temp;node1.end = node.end;node1.temp = node.start;push(&s, node1);node2.n = 1;node2.start = node.start;node2.end = node.end;node2.temp = node.temp;push(&s, node2);node3.n = node.n - 1;node3.start = node.start;node3.end = node.end;node3.temp = node.temp;push(&s, node3);}}}int main() {int n;printf("Enter the number of disks: "); scanf("%d", &n);hanoi(n, 'A', 'C', 'B');return 0;}```在这个非递归算法中,我们使用了一个栈来模拟递归的过程。
汉诺塔问题
![汉诺塔问题](https://img.taocdn.com/s3/m/695a27a5f524ccbff1218440.png)
汉诺塔百科名片汉诺塔初始状态汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。
上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上安大小顺序摞着64片黄金圆盘。
上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
目录由来汉诺塔与宇宙寿命concreteHAM:汉诺塔问题的程序实现由来汉诺塔与宇宙寿命concreteHAM:汉诺塔问题的程序实现展开编辑本段由来来源汉诺塔是源自印度神话里的玩具。
上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。
上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
传说在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。
印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。
不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。
僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
不管这个传说的可信度有多大,如果考虑一下把64片金片,由一根针上移到另一根针上,并且始终保持上小下大的顺序。
这需要多少次移动呢?这里需要递归的方法。
假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。
此后不难证明f(n)=2^n-1。
n=64时,f(64)= 2^64-1=18446744073709551615假如每秒钟一次,共需多长时间呢?一个平年365天有31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下,18446744073709551615/31556952=584554049253.855年这表明移完这些金片需要5845亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。
四柱汉诺塔非递归算法实现
![四柱汉诺塔非递归算法实现](https://img.taocdn.com/s3/m/60211be6172ded630b1cb6f1.png)
,:
Mo v e ( A, C ) ; h a n o i 3 ( n - 1 , B , A , C ) ;
}
l
三柱 汉诺塔 非 递归算 法 分析 : 先不 考虑 盘子 个数 , 我们 对 h a n o i 3 ( A , B , C ) 进 行 一 次 递 归展 开 , 如图 1 , 得 到一 棵 二 叉树 , 对图 1 二 叉 树
图 3 三 柱 汉 诺 四 次 递 归过 程
本文 考虑 带 四柱 的汉诺 塔 问题 , 四柱 汉诺 塔 问题 和三 柱 汉诺 塔 问题 的惟 一 区别就 是 增加 了一 个 柱,目 标 是用 最少 的移 动 次 数将 A柱 上 的 n个盘 子 通 过 B 柱和 C柱移 到 D柱 上 。 虽然 四柱 汉诺 塔只 L L = 柱汉 诺 塔 多一 个柱, 但 是解 决它 的难 度远 大 于三柱 汉诺 塔 。 对 于盘 数 为 n的 四柱 汉诺 塔 问题 , 可 以递 归地 定
h a n o i 3 ( r , A, C , D ) ;
பைடு நூலகம்
9 6 . 福建电脑 I 2 0 1 3 年 第u期
煎…堡… … 曼… 照
UJ } AN C0 M pt J T嚣随
h a n o i 4 ( n — r , B , A, C , D ) ;
B , B 一> D , D 一> A进 行循 环 。 v o i d o u t p u t ( i n t p r e s e n t _ l e v e l , i n t p o s i t i o n , i n t r ) { / 参数 分 别为 : 当前层 号 , 在 本层 的序 号 , 层 号 所
由汉诺塔游戏想到的汉诺塔简单非递归算法
![由汉诺塔游戏想到的汉诺塔简单非递归算法](https://img.taocdn.com/s3/m/bf599a9351e79b896802263c.png)
1的数 组 元 素 中 ,第 二 大 的 盘 子 存 放 在 下 标 为 2的数 组 元 素 中 ,依 此 类 推 。 下 标 为 0的 第 一 个 数 组 元 素 中 存 放 本 数 组 中 盘 子 的个 数 。假 设 有 k个 盘 子 ,则 初 始 状 态 数 组 a的第 一 个 元 素 a0的 值 为 k 表 示 有 k个 盘 [ 1 ( 子 ) al的 值 也 为 k 表 示 最 大 的 盘 子 k , [】 值 为 ,l 】 ( ) a2的 k1 a 1 一 , [ 的值 为 1 k ,数 组 b和 C的 所 有 元 素 全 为 0 。这
维普资讯
《 农业 网络信息》 0 8年第 6期 交 流 园地 20
由汉诺塔游 戏想 到的汉诺 塔简 单非递归算法
张 洪 庆
( 龙 江农业 经 济 职业 学院 ,黑 龙江 牡丹 江 17 4 ) 黑 5 0 1 摘 要: 汉诺塔 问题是 一个 古典 的数 学问题 , 也是 程 序设 计 中的经典 递 归问题 , 递 归算 法 由于 简 洁 清晰 , 大 家所 熟 悉 其 为
p o e u e e in.be a s e u sv lo i m ,a r a la t t u o i’ sm pe a d l a,wrte y a r ltv l r c d r s d sg c u e rc r ie ag rt h s we a e f mi r wih i i d e t t S i l n ce r itn b eaiey sm pe p o e u e wi eiin y o a i p to muc moy s a e n ti p r h te tc lm o eig o h we f i l r c d r t d fce c ftkng u o h h me r p c .I h spa e ,t e mah maia d ln fte To ro
汉诺塔python代码
![汉诺塔python代码](https://img.taocdn.com/s3/m/8dc91dd94bfe04a1b0717fd5360cba1aa8118cea.png)
汉诺塔python代码汉诺塔游戏是一种经典的益智游戏,它的规则非常简单,但是解决这个问题却需要一定的思维能力,而且它还可以通过编程来实现。
Python是一门非常流行的编程语言,因此在这里我们将介绍如何使用Python来实现汉诺塔游戏。
一、汉诺塔游戏的规则汉诺塔游戏有三个柱子和若干个盘子,每个盘子大小不同。
开始时,所有盘子都放在一个柱子上,按照从大到小的顺序排列。
目标是将所有盘子从起始柱子移动到目标柱子上,并保持原来的顺序不变。
在移动过程中必须遵守以下规则:1. 每次只能移动一个盘子;2. 盘子只能放在比它大的盘子上面;3. 不能将一个大盘子放在一个小盘子上面。
二、使用递归算法实现汉诺塔游戏递归算法是解决汉诺塔问题最常用的方法之一。
下面我们将介绍如何使用递归算法来实现汉诺塔游戏。
1. 定义函数首先我们需要定义一个函数来实现汉诺塔游戏。
在这个函数中,我们需要传入三个参数:起始柱子、目标柱子和盘子的数量。
def hanoi(start, target, n):2. 判断递归结束条件在递归过程中,我们需要判断递归结束的条件。
当n等于1时,表示只有一个盘子需要移动,此时我们可以直接将它从起始柱子移动到目标柱子上。
if n == 1:print(start, "->", target)3. 递归调用如果n大于1,则需要进行递归调用。
首先我们需要将n-1个盘子从起始柱子移动到辅助柱子上,然后再将最后一个盘子从起始柱子移动到目标柱子上,最后将n-1个盘子从辅助柱子移动到目标柱子上。
else:hanoi(start, other, n-1)print(start, "->", target)hanoi(other, target, n-1)4. 完整代码下面是完整的使用递归算法实现汉诺塔游戏的Python代码:def hanoi(start, target, n):if n == 1:print(start, "->", target)else:other = 6 - start - targethanoi(start, other, n-1)print(start, "->", target)hanoi(other, target, n-1)hanoi(1, 3, 3)三、使用非递归算法实现汉诺塔游戏除了递归算法,我们还可以使用非递归算法来实现汉诺塔游戏。
汉诺塔非递归算法研究
![汉诺塔非递归算法研究](https://img.taocdn.com/s3/m/d0b799cebb4cf7ec4afed08b.png)
( , , ,) 结 果 是 :- 2 1- ,— 3 1 2 3 13 2 1- 。 3 13 2 的 1- ,- 3 2 ,— ,— ,— ,- 2 -  ̄ -  ̄ -  ̄
1 汉诺塔 问题经典递归算法
汉诺塔问题假 设有三根柱子 , 编号为 12 3 开始 时 1柱上 、、, 有 n个 圆盘 , 圆盘从 底 向上 、 由大 到小叠在一起 , 目标 是将所有
Ab t a t sr c T we fHo o rb e a ls ia n tn e o e u sv r g a o ro n ip o lm sa ca s li s c frc rie p o r mmi g wa rv d e s o o e f w wh n r n t e ag r h c a n sp o e a y t v r o e l h loi m l l t
维普资讯
第2 5卷 第 5期
20 0 8年 5月
计算机 应 用与软 件
Co u e pi ai n n o wa e mp tr Ap l to s a d S f r c t
Vo . 5 No 5 12 .
Ma 0 v 2 08
圆盘 从 1柱 移 到 3柱 , 按 同 样 顺 序 叠 放 。 移 动 过 程 中 可 以 使 并
经 典 递 归算 法 的 问题 是 当 n取 大数 时 , 归 调 用 导 致 溢 出 。 递
汉诺 塔 非递 归算 法研 究
赵 东 跃
( 福州 大 学 工 程 技 术 学 院 福建 福州 300 ) 5 0 2
摘 要
汉诺 塔 ( o e f ao) T w r ni 问题 是 求 在 三 个柱 子 之 间 移 动 圆盘 的 方 法 , 是 递 9程 序 设 计 的 经 典 例 子 , oH 它 3 - 已经 证 明 其 时 间 复
汉诺塔问题算法思路
![汉诺塔问题算法思路](https://img.taocdn.com/s3/m/8884e413492fb4daa58da0116c175f0e7dd1195f.png)
汉诺塔问题算法思路
汉诺塔问题是一个经典的数学问题,要求将一堆大小不同的圆盘从柱子A移动到柱子C,其中每一次移动都需要满足以下条件:
1. 每次只能移动一个圆盘;
2. 大的圆盘不能放在小的圆盘上面。
如何实现这个问题的算法呢?以下是一些思路:
1. 递归算法
最常见的解决汉诺塔问题的方法就是递归。
我们可以将问题分解为三个步骤:
(1) 将n-1个圆盘从起始柱子A经过辅助柱子B移动到目标柱子C;
(2) 将最大的圆盘从起始柱子A移动到目标柱子C;
(3) 将n-1个圆盘从辅助柱子B经过起始柱子A移动到目标柱子C。
这个算法的递归终止条件是只有一个圆盘需要移动时,直接将其从起始柱子A移动到目标柱子C即可。
2. 非递归算法
除了递归算法,我们还可以使用非递归算法来解决汉诺塔问题。
具体的算法流程如下:
(1) 将起始柱子A、辅助柱子B和目标柱子C分别压入堆栈。
(2) 当堆栈不为空时,执行以下循环:
a. 弹出栈顶元素,得到当前需要移动的圆盘数目n、起始柱子A、
辅助柱子B和目标柱子C;
b. 如果n==1,直接将起始柱子A上的一个圆盘移动到目标柱子C上;
c. 否则将n-1个圆盘从起始柱子A移动到辅助柱子B上,再将第n个圆盘从起始柱子A移动到目标柱子C上,最后将n-1个圆盘从辅助柱子B移动到目标柱子C上。
d. 将移动后的三个柱子B、A和C按照起始柱子A、辅助柱子B 和目标柱子C的顺序压入堆栈,重复(2)直到堆栈为空。
以上就是汉诺塔问题的两种解决思路,大家可以根据自己的需要和理解选择适合自己的算法来解决这个问题。
python 汉诺塔 非递归方法解题
![python 汉诺塔 非递归方法解题](https://img.taocdn.com/s3/m/b3c92555cd7931b765ce0508763231126edb77a5.png)
python 汉诺塔非递归方法解题---随着编程语言的发展,算法问题解决的方式也在不断变化。
汉诺塔问题就是一个经典的算法问题,通常采用递归的方法来解决。
但是,非递归的方法同样可以解决汉诺塔问题,下面就让我们来看看如何用Python实现非递归方法解决汉诺塔问题。
汉诺塔问题的基本概念是这样的:给定三个柱子A、B、C,每个柱子上都放了若干个按照一定顺序排列的盘子,每个盘子都由一个数字标记,表示盘子的位置和大小。
任务是将所有的盘子从一个柱子移动到另一个柱子,移动过程中需要遵守以下规则:1. 每个盘子只能移动到比它小的柱子上;2. 三个柱子上的盘子不能重叠;3. 移动过程中不能使用柱子C。
非递归方法解决汉诺塔问题通常采用回溯法。
这种方法的基本思路是尝试将问题分解为更小的子问题,通过回溯不同的子问题的解来找到最终的解。
在汉诺塔问题中,我们可以将任务分解为将最大的盘子从柱子A移到柱子B,然后将中间大小的盘子从柱子A移到柱子C,最后将最小的盘子从柱子C移到柱子B。
通过这种方式,我们可以逐步解决汉诺塔问题。
下面是用Python实现非递归方法解决汉诺塔问题的代码:```pythondef hanoi(n, source, target, auxiliary):if n > 0:# 将n-1个盘子从source柱子移动到auxiliary柱子,再将最大的盘子从source移动到targ et柱子hanoi(n-1, source, auxiliary, target)# 将最大的盘子从auxiliary移动到target柱子print(f'Move disk {n} from {source} to {target}')# 将n-1个盘子从auxiliary柱子移动到target柱子hanoi(n-1, auxiliary, target, source)```在这个函数中,参数n表示盘子的数量,source表示起始柱子,target表示目标柱子,auxiliary表示辅助柱子。
Hanoi塔问题的非递归算法分析
![Hanoi塔问题的非递归算法分析](https://img.taocdn.com/s3/m/f1e091cc6137ee06eff918fc.png)
l 问题的提出
Ha o塔 问题是源 于一个 古老 的传说,在l 世纪末 ,欧 ni 9 洲出现 了一种名为Ha o塔的游戏 ,这种游戏最 早来 源于布 ni 拉玛神庙 的教 士。有三根石针 、B 、C,在A 上放有6 个 针 4
1 步操作。例如 当N 4 ,Ha o塔游戏过程如图2 - =时 ni 所示。 可见 ,通过此 表的移动过程可 以看 出,当N 4 ,共移 - =时
由C 针移至 针 。
那一步 的操作对象 是,_号盘 ,起 点 是 ,终 点是c 。按 v1 针 针 照这种 方式 ,从 中心 位置开始 ,逐渐 向两瑞扩 展 ,最终 能 够 确定所有操作步起 点和 终点。
3算法的实现
利用函数调用 法来实现Ha o塔非递归算法 ni
v i eetn m. n a : od d l i t it 1 manf i 1 f it , n n m=I i ,;
2 解决问题的方案 . 2
f1 有~ l设 个盘 子按照规则从 第 1 针移动 到第3 针所需要 的最 少操 作 数 为 ,则根 据Ha o 塔 的递 归性 和对 称性 可 ni 知,数列 1 须满足 :AIl = 时,而 当n 时有 - 4 l ≥2 .2 + ;由 A= n I - 可 ̄A+12/ . l;这 说明数列 nl是 以2 l + . - ( + l 11 +l 为公 比而 以 。12 + - 为首 项的等 比数列,所 以 + _ ¨ n l 22 ≥l, 1 lA l ≥l。所 以解决N l . p 1 个盘 子的Ha o塔 问题至少需要 ni
关键词:汉诺塔;递归;非递归;时间复杂性
中图分类号 :T 3 1 P 0. 6 文献标 识码 :A
.
文章编号 :10 .8 42 0 )20 4 .2 0 88 1(0 60 0 00
汉诺塔不递归算法 python
![汉诺塔不递归算法 python](https://img.taocdn.com/s3/m/bf320a6cbc64783e0912a21614791711cc797984.png)
汉诺塔(Tower of Hanoi)是一个经典的问题,它源自印度传说,相传在一个印度庙里,有一个圆座,圆座上套着三根铜柱,柱上套着64片黄金圆盘。
圆盘从大到小依序套在一根柱子上,而圆盘要从柱子上移至另一柱子上。
并且呢,规矩是穿小的不能套在大的上面,且每次只能移动一片。
有个传说是这样说的:世界末日来临前,大梵天要将这些圆盘从最左边的柱子移动到最右边的柱子上,如果在世界毁灭之前完成的话,世界就不毁灭了。
所以印度教徒一直想要研究这个问题,因为他们认为只要研究出汉诺塔的奥义,就能够通过移动圆盘,把世界毁灭的最终日期推迟。
但是即便是现代日常生活中,汉诺塔的问题也被广泛的用于算法科学的教学与理论研究之中。
那么究竟这个汉诺塔问题是怎样呢?究竟它的算法应该怎样编写呢?Python语言应该怎样实现它呢?下面就让我为你一一解答:一、汉诺塔问题背后的算法逻辑1. 汉诺塔问题的规则汉诺塔问题是经典的递归问题,它遵循以下规则:1)每次只能移动一个盘子;2)大盘子不能放在小盘子上面;3)只能在三根柱子之间移动盘子。
2. 汉诺塔问题的解法对于汉诺塔问题的解法,我们可以简单概括为以下三个步骤:A. 将n-1个盘子由A柱经过C柱移动到B柱;B. 将第n个盘子由A柱移动到C柱;C. 将n-1个盘子由B柱经过A柱移动到C柱。
二、非递归算法的实现在Python中,我们可以使用非递归算法来实现汉诺塔问题的解法。
下面给出一个示例代码:```pythondef hanoi(n, a, b, c):i = 1while n > 0:if n == 1:print("将第", n, "个盘子由", a, "移动到", c)else:print("将第", n, "个盘子由", a, "移动到", b)print("将第", n, "个盘子由", b, "移动到", c)print("将第", n, "个盘子由", c, "移动到", a)n -= 1```以上的代码中,我们使用了一个while循环来模拟递归的过程,实现了汉诺塔问题的非递归解法。
汉诺塔问题非递归算法
![汉诺塔问题非递归算法](https://img.taocdn.com/s3/m/99f0f6bcf605cc1755270722192e453610665b35.png)
汉诺塔问题非递归算法
汉诺塔问题是一个经典的递归算法问题,但也可以使用非递归的方式解决。
下面是一种非递归算法的实现思路:
1. 创建三个栈,分别命名为A、B、C,表示三个柱子。
2. 对于n个盘子的汉诺塔问题,首先将所有盘子按从大到小的顺序依次压入栈A中。
3. 定义一个变量count,用来记录移动步数,初始值为0。
4. 如果n为奇数,则执行步骤5;如果n为偶数,则执行步骤6。
5. 循环执行以下操作:
5.1 将栈A的栈顶元素弹出,放入栈B中;
5.2 将栈A中剩余的n-1个盘子移到栈C中;
5.3 将栈B中的盘子移到栈C中;
5.4 将栈A作为辅助栈,栈B作为目标栈,栈C作为源栈,重复步骤5.1~5.3,直到栈A为空。
6. 循环执行以下操作:
6.1 将栈A的栈顶元素弹出,放入栈C中;
6.2 将栈A中剩余的n-1个盘子移到栈B中;
6.3 将栈C中的盘子移到栈B中;
6.4 将栈A作为辅助栈,栈C作为目标栈,栈B作为源栈,重复步骤6.1~6.3,直到栈A为空。
通过上述非递归算法,可以按照汉诺塔问题的规则将所有的盘子从栈A移动到栈B,并记录移动的步骤数。
3-2汉诺塔的非递归实现
![3-2汉诺塔的非递归实现](https://img.taocdn.com/s3/m/58a8037749d7c1c708a1284ac850ad02de80078c.png)
3-2汉诺塔的⾮递归实现 汉诺塔实现的基本思路是:不断将n个盘的汉诺塔问题转换为2个(n-1)个盘的汉诺塔问题,⽤递归实现⽐较好理解。
设n盘问题为(n, a, b, c),其中参数如下结构体所定义,第⼀个参数表⽰需要移动的盘⼦的数量,第⼆个参数表⽰n个盘⼦起始所在柱⼦a, 第三个参数表⽰会被借⽤的柱⼦b, 第四个参数表⽰这 n个盘⼦所在的⽬标柱⼦c。
递归思路假设(n, a, b, c)表⽰把 a柱⼦上的n个盘借助b柱⼦移动到 c 柱⼦上,这个问题的递归求解⽅式是先把 a 柱⼦的(n-1)盘⼦借助c柱⼦移动到b柱⼦上(n-1, a, c, b),然后把 a 柱⼦剩下的⼀个盘⼦移动到 c 柱⼦上(1, a, b, c),最后把 b 柱⼦上的(n-1)个盘⼦移动到 c 柱⼦上(n-1, b, a, c)则问题求解可转换为对(n - 1, a, c, b)、(1, a, b, c)、(n - 1, b, a, c)这三个问题的求解,其中(1, a, b, c)不需要递归,可直接实现,将n个盘的汉诺塔问题转换为2个(n-1)个盘的汉诺塔问题,然后使⽤递归将(n-1)盘问题转换成(n-2)盘问题,直到盘数为1⾮递归的⽅式 递归⽅式本质上使⽤栈来实现的,所以如果采⽤⾮递归的⽅式也是使⽤栈来辅助实现。
但是若是⽤堆栈来实现的话,当将分解出的上述三个问题压⼊栈时,应该按照“需要先求解的问题后压⼊”的顺序,也就是压⼊顺序为:(n - 1, b, a, c), (1, a, b, c), (n - 1, a, c, b).1 typedef struct { //汉诺塔问题的结构类型2int N;3char A; //起始柱4char B; //借助柱5char C; //⽬标柱67 }ElementType; //汉诺塔问题的结构类型1//借助栈的⾮递归实现2void Hanoi(int n)3 {4 ElementType P, toPush;5 Stack S;67 P.N = n; P.A = 'a'; P.B = 'b'; P.C = 'c';8 S.top = -1;910 Push(&S, P);11while (S.top != -1) //当堆栈不为空时12 {13 P = Pop(&S);14if (P.N == 1)15 printf("%c -> %c\n", P.A, P.C);16else17 {18 toPush.N = P.N - 1;19 toPush.A = P.B; toPush.B = P.A; toPush.C = P.C;20 Push(&S, toPush); //将第⼆个待解⼦问题(n - 1, b, a, c)⼊栈21 toPush.N = 1;22 toPush.A = P.A; toPush.B = P.B; toPush.C = P.C;23 Push(&S, toPush); //将可直接求解的⼦问题(1, a, b, c)⼊栈24 toPush.N = P.N - 1;25 toPush.A = P.A; toPush.B = P.C; toPush.C = P.B;26 Push(&S, toPush); //将第⼀个待解⼦问题(n - 1, a, c, b)⼊栈27 }28 }29 }下⾯是栈的实现和主函数:1 #include <stdio.h>2#define MaxSize 10034 typedef struct {5 ElementType Data[MaxSize];6int top;7 }Stack; //堆栈的标准定义89void Push(Stack *PtrS, ElementType item)10 {11//⼊栈操作12if (PtrS->top == MaxSize)13 {14 printf("The stack is full!\n");15return;16 }17else18 {19 PtrS->Data[++(PtrS->top)] = item;20return;21 }22 }2324 ElementType Pop(Stack *PtrS)25 {26if (PtrS->top == -1)27 {28 printf("The stack is empty!\n");29return ERROR; //ERROR是ElementType的特殊值,标志错误30 }31else32 {33 PtrS->top--;34return (PtrS->Data[PtrS->top + 1]); //或者是return PtrS->Data[PtrS->top--];35 }36 }3738int main()39 {40int n;41 ERROR.N = -1; //ERROR是ElementType的特殊值,标志错误42 scanf_s("%d", &n);43 Hanoi(n);44return0;45 }。
汉诺塔问题算法描述
![汉诺塔问题算法描述](https://img.taocdn.com/s3/m/5e21a2783d1ec5da50e2524de518964bcf84d20b.png)
汉诺塔问题算法描述汉诺塔问题是一个经典的递归问题,其背后的算法思想可以推广到许多其他领域。
该问题的基本形式是:有三根柱子,A、B、C,A 柱子上有 n 个盘子,盘子大小不一,要将它们移到 C 柱子上,移动过程中可以借助 B 柱子,盘子移动时必须遵循以下规则:1. 每次只能移动一个盘子;2. 盘子可以放置在空柱子或比它大的盘子上;3. 盘子不能放置在比它小的盘子上。
汉诺塔问题是一个典型的递归问题,通过扩展汉诺塔问题的规模,可以引出更加深刻的递归思想和算法。
下面对汉诺塔问题的算法描述进行详细解释:1. 求解汉诺塔问题的递归算法求解汉诺塔问题的递归算法由三个部分组成:(1)将上面的 n-1 个盘子移动到 B 柱子上;(2)将最底下的一个盘子从 A 柱子移动到 C 柱子上;(3)将 B 柱子上的 n-1 个盘子移动到 C 柱子上。
基于以上三步,我们可以得到汉诺塔问题的递归算法:def hanoi(n, p1, p2, p3): if n == 1: print(p1, "->", p3) else: hanoi(n - 1,p1, p3, p2) print(p1, "->", p3) hanoi(n - 1, p2, p1, p3)该算法的时间复杂度为 O(2^n),由于需要移动 2^n-1 次,因此对于较大的 n 值,计算时间会非常长。
2. 求解汉诺塔问题的非递归算法上面提到的递归算法,虽然精简高效,但是对于大规模数据求解效率会很低。
而非递归算法,一般具有更好的时间复杂度、更低的计算成本。
接下来我们介绍如何通过栈数据结构来实现汉诺塔问题的非递归算法:(1)我们可以将每个子问题看作一个状态,用一个元组 (n, p1, p2, p3) 来表示状态,其中 n 表示当前状态还有多少个盘子需要移动,p1、p2、p3 分别表示 A、B、C 三个柱子的状态。
(2)我们将状态元组压入栈中,每次取出栈顶元组进行处理。
汉诺塔非递归表达式
![汉诺塔非递归表达式](https://img.taocdn.com/s3/m/59f67384112de2bd960590c69ec3d5bbfc0ada7a.png)
汉诺塔非递归表达式一、汉诺塔的简单介绍汉诺塔这个东西可有意思啦。
它就像是一个很神奇的数学谜题。
有三根柱子,一堆大小不一样的圆盘,开始的时候圆盘都在一根柱子上,按照规定的规则把圆盘从起始柱子移动到目标柱子,而且小圆盘要一直在大圆盘上面。
这看起来简单,其实里面的门道可深啦。
二、非递归表达式的思路1. 汉诺塔的移动是有规律的。
我们要知道,它的总移动步数是2的n次方减1步,这里的n就是圆盘的个数。
比如说有3个圆盘,那就是2的3次方减1等于7步。
2. 它的非递归算法就像是按照一个固定的步骤来走。
我们可以把汉诺塔的移动看作是一个整体的任务分解。
如果有n个圆盘,我们先把最上面的n - 1个圆盘当作一个整体,先把它们移动到中间柱子,然后把最底下的那个大圆盘移动到目标柱子,最后再把中间柱子上的n - 1个圆盘移动到目标柱子。
3. 用数学的方式来表示这个过程。
假设我们用A表示起始柱子,B表示中间柱子,C表示目标柱子。
当n = 1的时候,直接把圆盘从A移动到C就好啦。
当n > 1的时候,我们先把n - 1个圆盘从A 借助C移动到B,这一步就像是一个子任务。
然后把A柱子上剩下的那个最大的圆盘移动到C。
最后再把B柱子上的n - 1个圆盘借助A移动到C。
三、具体的非递归表达式1. 我们可以用一个简单的算法来描述这个过程。
可以用循环来处理这个移动过程。
比如用一个计数变量i,从1到2的n次方减1。
在这个循环里面,我们根据i的值来确定是哪一步移动,是移动小圆盘还是大圆盘。
2. 把每一步的移动看作是一种状态的转换。
如果i的值是奇数,那么我们就把最上面的圆盘从当前柱子移动到按照顺序的下一个柱子(如果当前柱子是A,下一个柱子就是C;如果当前柱子是C,下一个柱子就是B;如果当前柱子是B,下一个柱子就是A)。
如果i 的值是偶数,那么我们就把可以移动的圆盘(不是最上面的圆盘,而是在符合规则下的圆盘)从当前柱子移动到另外一个柱子(这个柱子不是按照顺序的下一个柱子,而是另外一个)。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
void setNext(Stake *p)
{
next=p;
}
Stake *getNext()//获取下一个对象的地址
{
return next;
}
int getName()//获取当前桩子的编号
{
return name;
}
private:
int s[Cap+1];//表示每根桩子放盘子的最大容量
int top,name;
最后,进行以下步骤即可:
(1)首先,按顺时针方向把圆盘1从现在的桩子移动到下一根桩子,即当n为偶数时,若圆盘1在桩子A,则把它移动到B;若圆盘1在桩子B,则把它移动到C;若圆盘1在桩子C,则把它移动到A。
(2)接着,把另外两根桩子上可以移动的圆盘移动到新的桩子上。
即把非空桩子上的圆盘移动到空桩子上,当两根桩子都非空时,移动较小的圆盘。
(3)重复(1)、(2)操作直至移动次数为2^n - 1。
#include<iostream>
#include<cmath>
using namespace std;
#define Cap 64
class Stake //表示每桩子上的情况
{
public:
Stake(int name,int n)
{
this->name=name;
Stake *next;
};
void ห้องสมุดไป่ตู้ain()
{
int n;
void hanoi(int,int,int,int);
cout<<"请输入盘子的数量:";
cin>>n;
if(n<1)
cout<<"输入的盘子数量错误!!!"<<endl;
else
{
cout<<"移动"<<n<<"个盘子的步骤如下:"<<endl;
}
else
{
temp=p->Pop();
cout<<p->getName()<<"-->";
p=p->getNext();
p->Push(temp);
cout<<p->getName()<<endl;
}
}
}
for(i=0;i<n;i++)//把n个盘子按顺序放在A桩子上
a.Push(n-i);
a.setNext(&b);
b.setNext(&c);//将3个桩子连在一起,就如同链表
c.setNext(&a);
for(i=0,p=&a;i<max;i++)//此处打印盘子的移动步骤
{
if(i%2)
{
ptr1=p->getNext();
if(n%2)
hanoi(n,1,3,2);
else
hanoi(n,1,2,3);
}
}
void hanoi(const int n,int A,int B,int C)
{
Stake a(A,n),b(B,n),c(C,n);
Stake *p,*ptr1,*ptr2,*pt;
int i,temp,max=pow(2,n)-1;
top=0;
s[top]=n+1;/*假设桩子最底部有第n+1个盘子,即s[0]=n+1,这样方便下面进行操作*/
}
int Top()//获取栈顶元素
{
return s[top];//栈顶
}
int Pop()//出栈
{
return s[top--];
}
void Push(int top)//进栈
{
s[++this->top]=top;
Make By Mr.Cai
思路介绍:
首先,可证明,当盘子的个数为n时,移动的次数应等于2^n - 1。
然后,把三根桩子按一定顺序排成品字型(如: ),再把所有的圆盘按至上而下是从小到大的顺序放在桩子A上。
接着,根据圆盘的数量确定桩子的排放顺序:
若n为偶数,按顺时针方向依次摆放 ;
若n为奇数,按顺时针方向依次摆放 。
ptr2=ptr1->getNext();
if(ptr1->Top()<ptr2->Top())
{
pt=ptr1;
ptr1=ptr2;
ptr2=pt;
}
ptr1->Push(ptr2->Pop());
cout<<ptr2->getName()<<"-->"
<<ptr1->getName()<<endl;