汉诺塔的非递归(演示动画).

合集下载

m根柱子的汉诺塔问题 c++

m根柱子的汉诺塔问题 c++

题目:C++中解决汉诺塔问题的方法一、引言汉诺塔问题是一个经典的数学问题,最早由法国数学家爱德华·卢卡斯在1883年发现并提出。

这个问题可以用来引出递归、分治等算法设计思想,也是程序设计中的经典问题之一。

本文将介绍如何使用C++语言来解决汉诺塔问题。

二、汉诺塔问题的描述汉诺塔问题的具体描述是:有三根柱子,标记为A、B、C,A柱子上有N个不同大小的圆盘,较大的圆盘必须始终位于较小的圆盘上。

要求将A柱子上的圆盘全部移动到C柱子上,并且在移动过程中始终保持较大的圆盘在下面,较小的圆盘在上面。

三、递归解法递归是解决汉诺塔问题的一种常用方法。

具体的解法可以描述为:1. 如果只有一个圆盘,直接将其从A柱子移动到C柱子即可;2. 如果有N个圆盘,那么可以将其分解为两个子问题:首先将N-1个圆盘从A柱子移动到B柱子,然后将最大的圆盘从A柱子移动到C柱子,最后将N-1个圆盘从B柱子移动到C柱子。

四、C++代码实现下面是使用C++语言实现汉诺塔问题的递归解法的代码示例:```cpp#include <iostream>using namespace std;void hanoi(int n, char from, char to, char aux) {if (n == 1) {cout << "Move disk 1 from " << from << " to " << to << endl;return;}hanoi(n - 1, from, aux, to);cout << "Move disk " << n << " from " << from << " to " << to << endl;hanoi(n - 1, aux, to, from);}int main() {int num_disks;cout << "Enter the number of disks: ";cin >> num_disks;hanoi(num_disks, 'A', 'C', 'B');return 0;```在这段代码中,hanoi函数是递归解决汉诺塔问题的核心代码。

汉诺塔问题的非递归算法设计及可视化实现

汉诺塔问题的非递归算法设计及可视化实现

汉诺塔问题的非递归算法设计及可视化实现彭伟【摘要】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根针,但要遵循的规则是:一次只能移动一个碟片,并且不允许将任何一个碟片放在比它小的碟片上面。

2024-2025学年人教版新教材信息技术五年级上册 第03课 游戏体验寻规律 教案

2024-2025学年人教版新教材信息技术五年级上册 第03课 游戏体验寻规律 教案

第3课游戏体验寻规律一、教学目标1.学生通过玩汉诺塔益智游戏,掌握其操作规律。

2.理解汉诺塔游戏中的算法,提升信息处理能力。

3.培养学生的逻辑思维和问题解决能力。

二、教学重点与难点教学重点1.掌握汉诺塔游戏的操作规律。

2.理解游戏中的算法。

教学难点1.分析和总结汉诺塔游戏的复杂规律。

2.运用算法解决汉诺塔游戏中的问题。

三、教学准备1.汉诺塔游戏道具若干套。

2.多媒体课件,展示汉诺塔游戏的介绍和玩法。

四、教学过程(一)导入新课师:同学们,今天我们来玩一个非常有趣的益智游戏——汉诺塔。

这个游戏不仅好玩,还能让我们学到很多知识呢。

大家有没有听说过汉诺塔游戏呢?(展示汉诺塔游戏的图片)(二)新课讲解1.汉诺塔游戏介绍(1)游戏规则师:汉诺塔游戏是由三根柱子和若干个大小不同的圆盘组成。

开始时,所有的圆盘都在一根柱子上,按照从大到小的顺序排列。

我们的任务是把这些圆盘全部移动到另一根柱子上,但是在移动的过程中,要遵守以下规则:①每次只能移动一个圆盘。

②大圆盘不能放在小圆盘上面。

(2)游戏目标师:我们的目标就是用最少的步数把所有的圆盘从一根柱子移动到另一根柱子上。

2.汉诺塔游戏的操作方法(1)以三个圆盘为例进行演示师:现在我们先来玩一个简单的汉诺塔游戏,有三个圆盘。

我们先把三个圆盘按照从大到小的顺序放在柱子A上。

(展示初始状态)第一步,我们把最小的圆盘从柱子A移动到柱子B。

(实际操作演示)第二步,把中间的圆盘从柱子A移动到柱子C。

第三步,把最小的圆盘从柱子B移动到柱子C。

第四步,把最大的圆盘从柱子A移动到柱子B。

第五步,把最小的圆盘从柱子C移动到柱子A。

第六步,把中间的圆盘从柱子C移动到柱子B。

第七步,把最小的圆盘从柱子A移动到柱子B。

(展示最终状态)(2)分析操作步骤师:我们来分析一下刚才的操作步骤。

首先,我们把最小的圆盘移动到了柱子B,这一步是为了给中间的圆盘腾出空间。

然后,我们把中间的圆盘移动到了柱子C,这一步是为了给最大的圆盘腾出空间。

汉诺塔问题的非递归新解法

汉诺塔问题的非递归新解法

汉诺塔问题的非递归新解法
熊小兵;苏光奎
【期刊名称】《三峡大学学报(自然科学版)》
【年(卷),期】2004(26)4
【摘要】汉诺塔问题是计算机算法设计中经常被大家引用来说明递归算法的一个经典问题.长期以来,很多人一直认为这个问题只能用递归方法求解.从讨论汉诺塔问题的几个基本特性入手,通过分析和归纳总结,提出了一种全新的解决汉诺塔问题的简洁而又高效的非递归解法,并用具体的实例对其进行了验证.
【总页数】4页(P375-378)
【作者】熊小兵;苏光奎
【作者单位】武汉大学,计算机学院,武汉,430079;武汉大学,计算机学院,武
汉,430079
【正文语种】中文
【中图分类】TP301.6
【相关文献】
1.由汉诺塔游戏想到的汉诺塔简单非递归算法 [J], 张洪庆
2.汉诺塔问题非递归算法的实现 [J], 朱玲
3.汉诺塔问题的非递归算法设计及可视化实现 [J], 彭伟
4.汉诺塔问题递归算法与非递归算法比较 [J], 肖红德
5.汉诺塔问题递归算法与非递归算法比较 [J], 肖红德
因版权原因,仅展示原文概要,查看原文内容请购买。

汉诺塔的非递归表达式

汉诺塔的非递归表达式

汉诺塔的非递归表达式汉诺塔这个问题呀,可有趣啦。

咱们先简单说说汉诺塔是个啥。

汉诺塔呢,就是有三根柱子,然后有一堆大小不一样的圆盘,一开始这些圆盘都在一根柱子上,按照从大到小的顺序堆着,就像一个塔一样。

我们要做的呢,就是把这些圆盘从这根柱子移动到另外一根柱子上,但是有个规则哦,大圆盘不能放在小圆盘上面。

那它的非递归表达式呢,这可有点小复杂啦。

我们可以从汉诺塔的移动步骤来分析。

每次移动圆盘的时候,其实是有一定规律的。

如果我们把汉诺塔的圆盘数量设为n。

当n = 1的时候,那很简单呀,直接把这个圆盘从起始柱子移动到目标柱子就好啦。

当n > 1的时候呢,我们可以把最上面的n - 1个圆盘看作一个整体,先把这n - 1个圆盘从起始柱子移动到中间柱子,这一步就像是在解决一个圆盘数量为n - 1的汉诺塔问题。

然后呢,把最下面的那个最大的圆盘从起始柱子移动到目标柱子。

最后呀,再把中间柱子上的n - 1个圆盘移动到目标柱子,这样就完成了整个汉诺塔的移动。

从这个过程里,我们就能慢慢推出它的非递归表达式啦。

这个表达式呀,要考虑到圆盘的数量、移动的方向还有当前的状态。

它其实是和一些数学规律有关的,像是和2的幂次方有点联系呢。

比如说,如果圆盘数量是3,那么移动的最少步数就是2的3次方减1,也就是7步。

这个规律其实就是非递归表达式的一部分哦。

再深入一点,我们可以想象一下汉诺塔的每一步移动就像是在一个特定的规则下进行的数学运算。

每一次把圆盘从一个柱子移动到另一个柱子,都对应着表达式里的一个变化。

就好像是在一个神秘的数学游戏里,我们要找到那个正确的公式,来描述这个汉诺塔的移动过程。

汉诺塔的非递归表达式虽然有点难理解,但是只要我们一步一步地去分析它的移动过程,就会发现其中的乐趣和奥秘啦。

就像探索一个神秘的宝藏一样,每发现一点关于表达式的线索,都会让我们更加兴奋呢。

汉诺塔问题动态演示

汉诺塔问题动态演示
void hanoi ( int n, char a, char b, char c ) { if ( n >= 1 ) { hanoi ( n-1, a, c, b) ; printf(“%c -->%c\n“,a,c); hanoi (n-1, b, a, c) ; } }
H(n,A,B,C)
H ( 3, A, B, C )
H(n,A,B,C)
H ( 3, A, B, C )
Stack
Output 0 C B A 1 C A B 2 A C B 3 A B C A A C B
H(n-1,a,c,b)
H ( 2, A, C, B )
H(n-1,b,a,c) H ( 1, C, A, B )
H(n-1,a,c,b) H ( 0, C, B , A)
H ( 3, A, B, C )
Stack
Output 0 A C B 1 C A B 2 A C B 3 A B C A A C C B B
H(n-1,a,c,b)
H ( 2, A, C, B )
H(n-1,b,a,c)
H ( 1, C, A, B )
H(n-1,b,a,c) H ( 0, A, C , B )
n a b c
void hanoi ( int n, char a, char b, char c ) { if ( n >= 1 ) { hanoi ( n-1, a, c, b) ; printf(“%c -->%c\n“,a,c); hanoi (n-1, b, a, c) ; } }
H(n,A,B,C)
H ( 3, A, B, C )
Stack
Output A A 1 C A B 2 A C B 3 A B C C C B B

汉诺塔问题非递归算法c语言

汉诺塔问题非递归算法c语言

汉诺塔问题非递归算法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;}```在这个非递归算法中,我们使用了一个栈来模拟递归的过程。

汉诺塔的非递归算法

汉诺塔的非递归算法

汉诺塔的⾮递归算法思路模拟递归程序执⾏过程,借助⼀个堆栈,把递归转成⾮递归算法。

转化过程1. 递归算法1void hanoi(int n, char from, char pass, char to) {2if (n == 0)3return;45 hanoi(n - 1, from, to, pass);6 move(n, from, to);7 hanoi(n - 1, pass, from, to);8 }2. 处理⾸递归 本函数第2⾏是结束条件,第5⾏开始进⼊⾸递归。

执⾏第5⾏函数调⽤之前,需要保留调⽤现场,本例中是4个参数⼊栈,使⽤新的参数调⽤hanoi函数。

⽽继续跟踪被调⽤的函数,可以看出需要⼀直进⾏⼊栈操作,直到参数n == 0为⽌。

对此⾏为,我们可以⽤⼀个循环来模拟:伪代码:int i = n;while (i != 0) { push(i);i --;} 现在可以断⾔ i ==0 ,满⾜函数返回的条件。

当函数返回后,需要通过pop操作来恢复现场,然后继续执⾏后⾯的语句。

为了简化问题,我们假设后⾯只有move()⼀条语句,执⾏完毕该语句后就继续向上⼀层回溯,直⾄最顶层,这样⼜可以⽤⼀个循环来模拟:伪代码:int i = n;while (i != 0) { push(i);i --;}while (栈不空) {int m = pop();move(m, ...);尾递归...}3. 处理尾递归 ⼀般⽽⾔,尾递归可以直接改成上⼀条语句的循环。

但在本例中,尾递归被嵌在另⼀个循环中,此时需要模拟它的⾏为:进⼊尾递归hanoi()函数后,需要执⾏其函数体,⽽函数体⼜是上述代码中的第⼀句话,可以如下表⽰:伪代码:a_new_beginning:int i = n;while (i != 0) { push(i);i --;}while (栈不空) {int m = pop();move(m, ...);产⽣新的参数,跳出循环,跳转到a_new_beginning语句处;} 相⽐于第⼀个while全部执⾏,第⼆个while实际只被执⾏⼀次就跳出来了,这种结构,很显然可以等价变换为外加⼀个⼤循环。

汉诺塔python代码

汉诺塔python代码

汉诺塔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)三、使用非递归算法实现汉诺塔游戏除了递归算法,我们还可以使用非递归算法来实现汉诺塔游戏。

基于策略模式的软件开发PPt讲解 汉诺塔问题

基于策略模式的软件开发PPt讲解 汉诺塔问题

研究的问题
汉诺塔问题是计算机算法设计中经常被大家引用来说明递归算 法的一个经典问题,长期以来,很多人认为这个问题只能用递 归方法求解,从讨论汉诺塔的几个基本特性入手,通过分析和 归纳总结,提出了一种全新的解决汉诺塔问题非递归解法
递归算法
Void hanoi(int n,char x,char y,char z)上按 //将塔座x上按直径由小到大且自上而下编号为1至nde 个圆盘按规则搬到塔 //座z上,y可用作辅助塔座。搬动操作move(x,n,z)可定义为(c是初值为0的 //全局变量,对搬动计数); 1{ (1)递归看似简洁,但是递归算法 2 if(n==1) 解题的运行效率较低 3 move(x,1,z); (2)在递归调用的过程中系统为每一层 4 else 的返回点、局部量等开辟了栈来存储 5 hanoi(n-1,x,z,y); 递归次数过多容易造成栈溢出,汉诺 6 move(x,n,z); 塔问题会多次用到递归 7 hanoi(n-1,y,x,z); 8 } 9 }
小结
实际上,为解决n个盘子的汉诺塔问题,数组S只需要2^n-1行即可;先求出n-1 个盘子的汉诺塔问题的解,然后根据S的内容输出n个盘子的汉诺塔问题的解,这 样空间开销句降低了一半,时间开销也有所改善。 目前,解决汉诺塔问题多数都是利用二叉树至是三叉树做为逻辑数据结构并通过 树的构造和遍历来实现的.这类算法虽然思想基础较简单,但空间开销和时间开销都 比较大,另有一些算法虽然空间和时间开销大有改善,但其导出过程比较复杂,一般 人难以领悟。 比较而言,本文介绍的递推算法不仅简单易行,而且其思想基础很容易把握。
计11-1 张春颖 37号 计11-1 刘 丹 22号
问题背景描述
汉诺塔游戏是这样的:有三个塔(塔1,塔2和塔3)和N个半径不同的盘子。初始 所有的盘子按半径从小到大堆叠在塔1上,半径最小的盘子在最上面。规则:每次 只可以移动一个塔上最顶端的盘子到另一个塔上,而且不可以把大盘子堆在小盘子 上。问题是要把所有盘子移动到塔3上。例如:有三个盘子分别命名为X,Y,Z的塔 座,在塔座X上插有n个直径大小各不相同,以小到大编号为1,2,……n的圆盘, 现要求将X轴上的n个圆盘移至塔座Z上并仍按同样顺序叠排,圆盘移动时必须遵循 下列规则: 1.每次只能移动一个圆盘; 2.圆可以插在X,Y和Z中的的任一塔座上; 3.任何时刻都不能将一个较大的圆盘压在较小的圆盘之上。

汉诺塔问题算法思路

汉诺塔问题算法思路

汉诺塔问题算法思路
汉诺塔问题是一个经典的数学问题,要求将一堆大小不同的圆盘从柱子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)直到堆栈为空。

以上就是汉诺塔问题的两种解决思路,大家可以根据自己的需要和理解选择适合自己的算法来解决这个问题。

Hanoi塔问题的非递归算法分析

Hanoi塔问题的非递归算法分析

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

汉诺塔(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循环来模拟递归的过程,实现了汉诺塔问题的非递归解法。

汉诺塔问题非递归算法

汉诺塔问题非递归算法

汉诺塔问题非递归算法
汉诺塔问题是一个经典的递归算法问题,但也可以使用非递归的方式解决。

下面是一种非递归算法的实现思路:
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,并记录移动的步骤数。

汉诺塔非递归表达式

汉诺塔非递归表达式

汉诺塔非递归表达式一、汉诺塔的简单介绍汉诺塔这个东西可有意思啦。

它就像是一个很神奇的数学谜题。

有三根柱子,一堆大小不一样的圆盘,开始的时候圆盘都在一根柱子上,按照规定的规则把圆盘从起始柱子移动到目标柱子,而且小圆盘要一直在大圆盘上面。

这看起来简单,其实里面的门道可深啦。

二、非递归表达式的思路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 的值是偶数,那么我们就把可以移动的圆盘(不是最上面的圆盘,而是在符合规则下的圆盘)从当前柱子移动到另外一个柱子(这个柱子不是按照顺序的下一个柱子,而是另外一个)。

3-2汉诺塔的非递归实现

3-2汉诺塔的非递归实现

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 }。

汉诺塔问题

汉诺塔问题

汉诺塔百科名片汉诺塔初始状态汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。

上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上安大小顺序摞着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亿年,太阳系的预期寿命据说也就是数百亿年。

汉诺塔问题的递归解法和非递归解法(python语言实现)

汉诺塔问题的递归解法和非递归解法(python语言实现)

汉诺塔问题的递归解法和⾮递归解法(python语⾔实现)1. 汉诺塔问题的⾮递归解法(python语⾔类解法)#!/usr/bin/env python#coding:utf-8import sysimport timereload(sys)sys.setdefaultencoding('utf-8')class Mycolumns(object):val=0#__slots__ = ['plates','name']def __init__(self,name='',plates_num=0): = nameself.plates = []if plates_num > 0 :for i in range(0,plates_num):self.plates.append(n-i)@staticmethoddef fun():Mycolumns.val +=1print"this is the %d th time to move" %(Mycolumns.val)【这段可以⽤类⽅法代替】【@classmethoddef fun(cls):cls.val +=1print"this is the %d th time to move" %(cls.val)】def initialize(n):stack = []mycolumn1 = Mycolumns('A',n)if n%2 == 0:mycolumn2 = Mycolumns('B')mycolumn3 = Mycolumns('C')index = 2else:mycolumn2 = Mycolumns('C')mycolumn3 = Mycolumns('B')index = 1stack.append(mycolumn1)stack.append(mycolumn2)stack.append(mycolumn3)return stack,indexdef nowcolumn(i,stack):for item in stack:if i in item.plates:return itemdef nextcolumn(i,stack):for item in stack:if i in item.plates:if i%2!=0:next = (stack.index(item)+1)%3else:next = (stack.index(item)+2)%3#print "%d next column is %s"%(i,stack[next].name)return stack[next]def move(nowcolumn,nextcolumn):n = nowcolumn.plates.pop()nextcolumn.plates.append(n)print "move plate %d from %s to %s" %(n,,)Mycolumns.fun()def hannuoyi(n):stack,index = initialize(n)#max = pow(2,n)-1#k =0#while(k<max): FINAL = [] for i in range(0,n): FINAL.append(n-i) while(stack[index].plates!=FINAL):for i in range(1,n+1):#print "i value is %d" %(i)if(nowcolumn(i,stack).plates.index(i)==len(nowcolumn(i,stack).plates)-1 and (nextcolumn(i,stack).plates==[] or i< nextcolumn(i,stack).plates[-1])): move(nowcolumn(i,stack),nextcolumn(i,stack))#k = k+1else:pass#print"can not move plate %d" %(i)print stack[0].plates,stack[0].nameprint stack[1].plates,stack[1].nameprint stack[2].plates,stack[2].nameif __name__=="__main__":n=3hannuoyi(n) 2. 汉诺塔问题的⾮递归解法(python语⾔过程式解法)#!/usr/bin/env python#coding:utf-8import sysimport timereload(sys)sys.setdefaultencoding('utf-8')global aa =0def fun():global aa = a+1print"this is the %d th time to move" %(a)def nowcolumn(i,stackA,stackB,stackC):if i in stackA:return stackAelif i in stackB:return stackBelse:return stackCdef nextcolumn(n,i,stackA,stackB,stackC):if n%2==0:if i in stackA:if i%2!=0:newcolumn = stackBelse:newcolumn = stackCif i in stackB:if i%2!=0:newcolumn = stackCelse:newcolumn = stackAif i in stackC:if i%2!=0:newcolumn = stackAelse:newcolumn = stackBelse:if i in stackA:if i%2==0:newcolumn = stackBelse:newcolumn = stackCif i in stackB:if i%2==0:newcolumn = stackCelse:newcolumn = stackAif i in stackC:if i%2==0:newcolumn = stackAelse:newcolumn = stackBreturn newcolumndef move(nowcolumn,nextcolumn):n = nowcolumn.pop()nextcolumn.append(n)print "move plate %d" %(n)fun()def hannuoyi(n):stackA = []stackB = []stackC = []FINAL = []for i in range(0,n):stackA.append(n-i)FINAL.append(n-i)print stackA,stackB,stackC,FINALwhile(stackC!=FINAL):for i in range(1,n+1):print "i value is %d" %(i)if(nowcolumn(i,stackA,stackB,stackC).index(i)==len(nowcolumn(i,stackA,stackB,stackC))-1 and (nextcolumn(n,i,stackA,stackB,stackC)==[] or i< nextcolumn(n,i,stackA,stackB,stackC)[-1])):move(nowcolumn(i,stackA,stackB,stackC),nextcolumn(n,i,stackA,stackB,stackC))else:print"can not move plate %d" %(i)print stackA,stackB,stackCif __name__=="__main__":n=6hannuoyi(n)2. 汉诺塔问题的递归解法(python语⾔)#!/usr/bin/env python#coding:utf-8import sysreload(sys)sys.setdefaultencoding('utf-8')global aa =0def fun():global aa = a+1def hannuoyi(n,A,B,C):if n==1:move(1,A,C)else:hannuoyi(n-1,A,C,B)move(n,A,C)hannuoyi(n-1,B,A,C)def move(n,tempA,tempB):print "move plate %d from column %s to column %s" %(n,tempA,tempB)fun()if __name__=="__main__":hannuoyi(3,'A','B','C')print "total:we need %d steps"%(a)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

汉诺塔的非递归(演示、动画)Hanoi,非递归,演示,动画效果kensta有动画演示,move2()是标准解的调用move()是用于演示动画或显示移动秩序和包含监测有无错误移动的调用使用Borland c++ 3.0(Turbo c++ 3.0,Turbo c 2.0也可)编译通过,图形方式使用Tc 的bgi*//*************************************//*about error process*/#include <stdlib.h>#include <string.h>#include <stdio.h>/*if debuging use #define ERROR_DEBUGotherwise remove it.*///#define ERROR_DEBUG#ifdef ERROR_DEBUG#define error(x) error_debug(x)#define report() report_debug()#define initerror() initerror_debug() char *err[10];int errs=0;void initerror_debug(){int i;for(i=0;i<10;i++)err[i]=NULL;}void error_debug(char *a){if(errs>9)return;err[errs]=(char *)malloc(strlen(a)+1); strcpy(err[errs],a);printf(a);errs++;}void report_debug(){int i;if(!errs)return;for(i=0;i<errs;i++){printf(err[i]);free(err[i]);}}#else#define error(x)#define report()#define initerror()#endif/*************************************/ /*about stack*/#define STACK_SIZE 31typedef struct {int data[STACK_SIZE];int top;}stack;int clear(stack *a);int create(stack **a);int push(stack *a,int data);int pop(stack *a,int *data);int gettop(stack *a,int *data);int dispose(stack *a);int pop(stack *a,int *data){if(a->top){*data=a->data[--a->top];return 1;}else{error("pop(stack *,int *):stack empty!\n"); return 0;}}int push(stack *a,int data){if(a->top<STACK_SIZE){a->data[a->top++]=data;return 1;}else {error("push(stack *,int):stack full!\n"); return 0;}}int create(stack **a){*a=(stack *)malloc(sizeof(stack));if(*a)return clear(*a);else{error("create(stack **):create error! Not enough momery!\n"); return 0;}}int clear(stack *a){if(a){a->top=0;return 1;}else {error("clear(stack *):stack not exist!\n");return 0;}}int gettop(stack *a,int *data){if(a->top){*data=a->data[a->top-1];return 1;}else{error("gettop(stack *,int *):stack empty!\n");return 0;}}int dispose(stack *a){if(a){free(a);return 1;}else{error("dispose(stack *):stack not exist!\n"); return 0;}}/**************************************//*about Hanoi the game*/#include <graphics.h>#include <dos.h>#define MAX_LEVEL STACK_SIZEint position[MAX_LEVEL+1];stack *theStack[3];int depth;int mode;int print;int initgame(int d){int i;int x,y;int h=5;int w;initerror();if(mode){int gdriver = DETECT, gmode, errorcode; /* initialize graphics mode */initgraph(&gdriver, &gmode, ""); setfillstyle(1,7);}for(i=0;i<3;i++)if(!create(&theStack[i]))break;if(i!=3){for(;i>=0;i--)dispose(theStack[i]);error("initgame(int):can not init stack!\n"); return 0;}depth=d;for(i=d;i;i--){push(theStack[0],i);if(mode){y=200+100-theStack[0]->top*(h+1);w=i*10;x=150-w/2;setcolor(i);setfillstyle(1,i);bar(x,y,x+w,y+h);}position[i]=0;}if(mode){setcolor(15);for(i=0;i<3;i++)rectangle(150+i*150-1,120,150+i*150+1,300); line(50,300,500,300);}return 1;}int endgame(){int i=2;for(;i>=0;i--)dispose(theStack[i]);printf("report:");report();if(mode)closegraph();return 1;}void show(int p,int from,int to){int i;int x,y;int newx,newy;int h=5;int w=p*10;y=200+100-(theStack[from]->top+1)*(h+1);x=from*150+150-w/2;newx=to*150+150-w/2;newy=200+100-theStack[to]->top*(h+1);while(y>100){setcolor(0);setfillstyle(1,0);bar(x,y,x+w,y+h);y-=(h+1);setcolor(15);rectangle(150+from*150-1,120,150+from*150+1,300);setcolor(p);setfillstyle(1,p);bar(x,y,x+w,y+h);delay(10);}while(x!=newx){setcolor(0);setfillstyle(1,0);bar(x,y,x+w,y+h);(x>newx)?x--:x++;setcolor(p);setfillstyle(1,p);bar(x,y,x+w,y+h);delay(2);}while(y<newy){setcolor(0);setfillstyle(1,0);bar(x,y,x+w,y+h);setcolor(15);rectangle(150+to*150-1,120,150+to*150+1,300); y+=(h+1);setcolor(p);setfillstyle(1,p);bar(x,y,x+w,y+h);delay(10);}}int move(int p){int t,s;if(!gettop(theStack[position[p>,&t)){error("move(int):the stack is empty\n");return 0;}if(t==p){pop(theStack[position[p>,&t);if(!mode&&print)printf("%c -> ",'A'+position[p]);/* another important core line */s=(position[p]+1+(depth%2?p%2:(p+1)%2) )%3;if(gettop(theStack[s],&t)&&t<p){error("move(int):can not move big level above small one\n");return 0;}push(theStack[s],p);if(mode)show(p,position[p],s);else if(print)printf("%c\t",'A'+s);position[p]=s;}else error("move(int):position error\n");return 1;}int move2(int p){int t,s;s=(position[p]+1+(depth%2?p%2:(p+1)%2) )%3;if(print)printf("%c->%c\t",'A'+position[p],'A'+s); position[p]=s;return 1;}#include <conio.h>void main(){unsigned long i;unsigned long N=10;unsigned long p,q;printf("Welcome to Hanoi\n");printf("Note that this Hanoi is not write by recurrence!\n"); printf("And not calculate with any stack.\n");printf("but i want to check if the a is right.\n");printf("i use 3 stack to show if there is any violent move happens.:)\n"); printf("\nEnter a number as level(1 to 30):");scanf("%d",&N);if(N<1||N>30){printf("error: not 1 to 30\n");return;}printf("\n Select show mode('c' in TEXT 'g' in GRAPHICS)\n");printf("Note that if the level is to big you'd better not use 'g' for speed.\n"); printf("19 is about 20 seconds. 20 is about double of that. etc.\n");printf("I test on a intel 166mmx cpu. 30 may be 40*1024 seconds.\n"); printf("wish you succeed!\n");switch(getch()){case 'c':printf("do you want to show the result?(y/n)\n");printf("print result will be slow!!!\n");do{mode=getch();if(mode=='y')print=1;if(mode=='n')print=0;}while(mode!='y'&&mode!='n');mode=0;case 'g':mode=1;break;default:printf("error: neither 'c' nor 'g'\n");return; }printf("processing...\n");initgame(N);/*core here!!!only 8 lines, ha!here get the level queueas 1 2 1 3 1 2 1 4 1 2 1 3 1 2 1*/for(i=1;i<(1L<<N);i++){q=1L<<N;p=N+1;while(q&&i%q){q>>=1;p--;}if(mode||print)move(p);else move2(p);}printf("ok\n");endgame(); }。

相关文档
最新文档