汉诺塔问题与函数递归调用
汉诺塔的递归算法

汉诺塔的递归算法1. 汉诺塔问题简介汉诺塔是一种经典的递归问题,常用于理解和展示递归算法的思想。
该问题由法国数学家爱德华·卢卡斯于19世纪初提出,得名于印度传说中一个传说故事。
现代汉诺塔问题由3个塔座和一些盘子组成,目标是将所有盘子从一个塔座上移动到另一个塔座上,遵循以下规则:1.一次只能移动一个盘子;2.大盘子不能放在小盘子上面。
2. 汉诺塔问题的递归解法汉诺塔问题的递归解法是一种简洁、优雅且高效的解决方案。
递归算法是一种将大问题划分为更小子问题的方法,通过递归地解决子问题来解决整个问题。
2.1. 基本思想以三个塔座A、B、C为例,假设有n个盘子需要从A移动到C。
递归算法的基本思想如下:1.将n个盘子分成两部分:最底下的一个盘子和上面的n-1个盘子;2.将上面的n-1个盘子从塔座A移动到塔座B,目标塔座为C;3.将最底下的一个盘子从塔座A移动到塔座C;4.将塔座B上的n-1个盘子移动到塔座C,目标塔座为A。
2.2. 递归实现递归解决汉诺塔问题的关键在于理解递归的调用和返回过程。
具体的递归实现如下:def hanoi(n, a, b, c):# n表示盘子的数量,a、b、c表示3个塔座if n == 1:print("Move disk from", a, "to", c)else:hanoi(n-1, a, c, b)print("Move disk from", a, "to", c)hanoi(n-1, b, a, c)# 调用递归函数hanoi(3, 'A', 'B', 'C')上述代码中,当n等于1时,直接将盘子从塔座A移动到塔座C。
否则,递归地将上面的n-1个盘子从塔座A移动到塔座B,然后将最底下的一个盘子从A移动到C,最后再将塔座B上的n-1个盘子移动到塔座C。
汉诺塔问题

汉诺塔问题递归调用的内部执行过程:1.运行开始时,首先为递归调用建立一个工作栈,其结构包括值参,局部变量,和返回地址;2.每次执行递归调用之前,把递归函数的值参和局部变量的当前值及调用后的返回地址入栈;3.每次递归调用结束后,将栈顶元素出栈,使相应的值参和局部变量恢复为调用前的值,然后转向返回地址指定的位置继续执行。
#include <iostream>using namespace std;void Move(char A,char C);void Hanoi(int n,char A,char B,char C);void main(){cout<<"***************汉诺塔问题***************"<<endl;int n;cout<<"输入塔A上原始盘子的数目:";cin>>n;cout<<"^^^^^^^^^^^^^^^^^具体移动过程如下:"<<endl;Hanoi(n,'A','B','C');}void Move(char A,char C){cout<<A<<"--->"<<C<<endl;}void Hanoi(int n,char A,char B,char C){if(n==1)Move(A,C);else{Hanoi(n-1,A,C,B);Move(A,C);Hanoi(n-1,B,A,C);}}。
【C语言程序设计】汉诺塔问题,用C语言实现汉诺塔!

【C语⾔程序设计】汉诺塔问题,⽤C语⾔实现汉诺塔!汉诺塔问题是指:⼀块板上有三根针 A、B、C。
A 针上套有 64 个⼤⼩不等的圆盘,按照⼤的在下、⼩的在上的顺序排列,要把这 64 个圆盘从 A 针移动到 C 针上,每次只能移动⼀个圆盘,移动过程可以借助 B 针。
但在任何时候,任何针上的圆盘都必须保持⼤盘在下,⼩盘在上。
从键盘输⼊需移动的圆盘个数,给出移动的过程。
算法思想对于汉诺塔问题,当只移动⼀个圆盘时,直接将圆盘从 A 针移动到 C 针。
若移动的圆盘为 n(n>1),则分成⼏步⾛:把 (n-1) 个圆盘从 A 针移动到 B 针(借助 C 针);A 针上的最后⼀个圆盘移动到 C 针;B 针上的 (n-1) 个圆盘移动到 C 针(借助 A 针)。
每做⼀遍,移动的圆盘少⼀个,逐次递减,最后当 n 为 1 时,完成整个移动过程。
因此,解决汉诺塔问题可设计⼀个递归函数,利⽤递归实现圆盘的整个移动过程,问题的解决过程是对实际操作的模拟。
程序代码#include <stdio.h>int main(){int hanoi(int,char,char,char);int n,counter;printf("Input the number of diskes:");scanf("%d",&n);printf("\n");counter=hanoi(n,'A','B','C');return0;}int hanoi(int n,char x,char y,char z){int move(char,int,char);if(n==1)move(x,1,z);else{hanoi(n-1,x,z,y);move(x,n,z);hanoi(n-1,y,x,z);}return0;}int move(char getone,int n,char putone){static int k=1;printf("%2d:%3d # %c---%c\n",k,n,getone,putone);if(k++%3==0)printf("\n");return0;}调试运⾏结果:当移动圆盘个数为 3 时,具体移动步骤如下所⽰:Input the number of diskes:31: 1 # A---C2: 2 # A---B3: 1 # C---B4: 3 # A---C5: 1 # B---A6: 2 # B---C7: 1 # A---C总结:本实例中定义的 hanoi() 函数是⼀个递归函数,它有四个形参"n""x""y""z"。
汉诺塔问题实验报告

1.实验目的:通过本实验,掌握复杂性问题的分析方法,了解汉诺塔游戏的时间复杂性和空间复杂性。
2.问题描述:汉诺塔问题来自一个古老的传说:在世界刚被创建的时候有一座钻石宝塔(塔A),其上有64个金碟。
所有碟子按从大到小的次序从塔底堆放至塔顶。
紧挨着这座塔有另外两个钻石宝塔(塔B和塔C)。
从世界创始之日起,婆罗门的牧师们就一直在试图把塔A 上的碟子移动到塔C上去,其间借助于塔B的帮助。
每次只能移动一个碟子,任何时候都不能把一个碟子放在比它小的碟子上面。
当牧师们完成任务时,世界末日也就到了。
3.算法设计思想:对于汉诺塔问题的求解,可以通过以下三个步骤实现:(1)将塔A上的n-1个碟子借助塔C先移到塔B上。
(2)把塔A上剩下的一个碟子移到塔C上。
(3)将n-1个碟子从塔B借助于塔A移到塔C上。
4.实验步骤:1.用c++ 或c语言设计实现汉诺塔游戏;2.让盘子数从2 开始到7进行实验,记录程序运行时间和递归调用次数;3.画出盘子数n和运行时间t 、递归调用次数m的关系图,并进行分析。
5.代码设计:Hanio.cpp#include"stdafx.h"#include<stdlib.h>#include<stdio.h>#include<iostream>void hanoi(int n,char x,char y,char z){if(n==1){printf("从%c->搬到%c\n",x,z);}else{hanoi(n-1,x,z,y);printf("从%c->%c搬到\n",x,z);hanoi(n-1,y,x,z);}}void main(){int m ;printf("input the number of diskes:");scanf("%d",&m);printf("The step to moving %3d diskes:",m);hanoi(m,'a','b','c');}自定义头文件:#pragma once#include"targetver.h"#include<stdio.h>#include<tchar.h>结果如下:6.递归应用中的Hanoi塔问题分析1)Hanoi塔问题中函数调用时系统所做工作一个函数在运行期调用另一个函数时,在运行被调用函数之前,系统先完成3件事:①将所有的实参、返回地址等信息传递给被调用函数保存。
汉诺塔问题

盐城工学院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 符号常量的定义常量就是在程序运行过程中其值不发生变化的量。
汉诺塔问题算法

汉诺塔问题算法汉诺塔问题是一个经典的数学问题和递归算法问题。
在汉诺塔问题中,有三个柱子,分别称为A、B、C,有一组大小不同的圆盘,开始时,这些圆盘都堆叠在A柱子上,目标是将所有的圆盘从A柱子移动到C柱子上,期间可以借助B柱子。
以下是汉诺塔问题的算法实现:1.如果只有一个圆盘,直接将其移动到C柱子上。
2.如果有多个圆盘(n个),先将上面的n1个圆盘从A柱子移动到B柱子上。
a.将上面的n1个圆盘从A柱子移动到C柱子,此时B柱子作为辅助柱子。
b.将最下面的第n个圆盘从A柱子移动到C柱子。
3.最后将B柱子作为起始柱子,A柱子作为辅助柱子,将B 柱子上的n1个圆盘移动到C柱子上。
实现递归函数hanoi(n,start,aux,end):如果n=1,直接将start柱子上的圆盘移动到end柱子上。
否则,将上面的n1个圆盘从start柱子移动到aux柱子。
调用递归函数hanoi(n1,start,end,aux),将start柱子上的n1个圆盘移动到aux柱子上。
将第n个圆盘从start柱子移动到end柱子上。
调用递归函数hanoi(n1,aux,start,end),将aux柱子上的n1个圆盘移动到end柱子上。
调用递归函数hanoi(n,'A','B','C')可以解决汉诺塔问题,其中n表示圆盘的数量,'A'、'B'、'C'表示三个柱子。
以上是汉诺塔问题的基本算法。
通过递归调用,可以有效地解决汉诺塔问题,但是当圆盘数量较大时,计算量会变得非常大。
因此,在实际应用中需要考虑到算法的优化和效率问题。
数据结构求解汉诺塔问题的递归算法

数据结构求解汉诺塔问题的递归算法汉诺塔问题是一个经典的数学问题,它可以通过递归算法来求解。
在这个问题中,我们需要将一堆盘子从一个柱子移动到另一个柱子,同时遵守以下规则:一次只能移动一个盘子,大盘子不能放在小盘子上面。
为了解决这个问题,我们可以使用数据结构中的栈来模拟柱子的堆叠。
我们可以将每个柱子表示为一个栈,每个盘子表示为一个元素。
初始时,所有的盘子都在第一个柱子上,我们需要将它们移动到第三个柱子上。
下面是求解汉诺塔问题的递归算法的伪代码:```1. 定义一个函数hanoi,接受参数n、起始柱子A、辅助柱子B、目标柱子C2. 如果n等于1,则直接将盘子从A移动到C3. 否则,将n-1个盘子从A移动到B,借助C作为辅助柱子4. 将第n个盘子从A移动到C5. 将n-1个盘子从B移动到C,借助A作为辅助柱子```接下来,我们来详细解释一下这个算法。
首先,我们定义了一个函数hanoi,它接受四个参数:n表示盘子的数量,起始柱子A、辅助柱子B和目标柱子C。
在函数内部,我们首先判断如果n等于1,那么我们直接将盘子从A移动到C即可。
这是递归算法的终止条件。
如果n大于1,我们需要将n-1个盘子从A移动到B,借助C作为辅助柱子。
这一步是通过递归调用hanoi函数来实现的。
在递归调用中,我们将n-1作为新的盘子数量,A作为起始柱子,B作为目标柱子,C作为辅助柱子。
接下来,我们将第n个盘子从A移动到C。
这一步是直接操作的,不需要递归调用。
最后,我们需要将n-1个盘子从B移动到C,借助A作为辅助柱子。
同样地,我们通过递归调用hanoi函数来实现这一步。
在递归调用中,我们将n-1作为新的盘子数量,B作为起始柱子,C作为目标柱子,A作为辅助柱子。
通过这样的递归调用,我们可以将所有的盘子从起始柱子A移动到目标柱子C,同时遵守汉诺塔问题的规则。
总结起来,数据结构中的栈可以很好地模拟汉诺塔问题中的柱子堆叠,而递归算法则可以很好地解决这个问题。
汉诺塔问题实验报告

游戏的时间复杂性和空间复杂性。 2.问题描述:
汉诺塔问题来自一个古老的传说:在世界刚被创建的时候有 一座钻石宝塔(塔 A),其上有 64 个金碟。所有碟子按从大到小的次 序从塔底堆放至塔顶。紧挨着这座塔有另外两个钻石宝塔(塔 B 和 塔 C)。从世界创始之日起,婆罗门的牧师们就一直在试图把塔 A 上的碟子移动到塔 C 上去,其间借助于塔 B 的帮助。每次只能移 动一个碟子,任何时候都不能把一个碟子放在比它小的碟子上面。 当牧师们完成任务时,世界末日也就到了。 3.算法设计思想:
8、总结
5
缓存大小
通过对汉诺塔算法的分析让我更清楚的认识到了不同的算法对 程序性能的影响,也让我明白掌握了算法将会有助于提高软件的开 发。
6
2)Hanoi 塔问题递归程序的复杂度分析
① 运行 hanoi 程序的时间
程序 hanoi.c 在硬件环境为赛扬 400MHz、内存 128M 的计算平台 (不同机器运行时间有一定差别)运行,可得出如下时间结果:
盘子数
时间结果
<=12 个
<=1 秒
14 个
2秒
16 个
13 秒
20 个
204 秒
② 时间复杂度
自定义头文件 :#pragma once
#include "targetver.h" #include <stdio.h> #include <tchar.h>
结果如下:
2
6.递归应用中的 Hanoi 塔问题分析 1)Hanoi 塔问题中函数调用时系统所做工作
一个函数在运行期调用另一个函数时,在运行被调用函数之前,系 统先完成 3 件事:
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
2个盘子时:
1、AB 2、AC 3、BC
4、AC 5、BA
6、BC 7、AC 2个盘子 从BC
}
10
应用实例
4个盘子时:
1、2个盘 子从AC 2、AB
函数源程序如下:
1、AB 2、 AC 3、B C 4、AB 5、CA 6、 CB 7、A B 8、AC 1、2个盘 子从BA 2、BC 3、2个盘 子从AC 9、BC 10、 BA 11、C A 12、BC
算法设计如下:
1、编写求年龄的函数age; 2、判断n=1时,返回值3; 3、判断n≥2时,函数age调用age(n-1)+2; 4、编写主调函数,调用递归函数。
函数程序如下:
int age(int n) { if(n==1) //求年龄函数 return 3;
else return age(n-1)+2; }
} void hanoi(int n,char A,char B,char C) { if(n==1) printf("%c -> %c\n",A,C);
1、3个盘 子从AB
3、2个盘 子从CB
2、AC
3、3个盘 子从BC
13、AB 14、 AC 15、B C
11
应用实例
函数源程序如下: 多个盘子算法设计如下:
9+2=11
7+2=9 5+2=7 3+2=5
age(2)+2
age(1)+2
3
第五个小朋友的年龄为11岁
5
应用实例
【汉诺塔游戏】 有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求将 所有圆盘移至C杆。移动的过程始终保持大盘在下,小盘在上的原则。
A
C
B
6
应用实例
【汉诺塔游戏】 有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求将 所有圆盘移至C杆。移动的过程始终保持大盘在下,小盘在上的原则。
实例分析如下:
1、AC
A
C
B
7
应用实例
【汉诺塔游戏】 有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求将 所有圆盘移至C杆。移动的过程始终保持大盘在下,小盘在上的原则。
3
A->C A->B C->B A->C B->A B->C A->C
12
总结
SUMMARY
1 2 3
单击此处添加文字内容 案例引入递归调用定义 单击此处添加文字内容 案例分析使用递归实现
单击此处添加文字内容 递归调用应用实例
谢谢!
1、把n-1个盘子由A B 2、把第n个盘子由AC 3、把n-1个盘子由B C
运行结果
void hanoi(int n,char A,char B,char C) { if(n==1) printf("%c -> %c\n",A,C); else { hanoi(n-1,A,C,B); printf("%c -> %c\n",A,C); hanoi(n-1,B,A,C); } } main() { int n; scanf("%d",&n); hanoi(n,'A','B','C'); } //主函数
2个盘子从AB
2个盘子从BC
6、BC
7、AC A C B
9
应用实例
函数源程序如下:
语句编写
只有1个盘子时:
1、AC
3个盘子时:
1、AC 2、AB 3、CB 2个盘子 从AB
void hanoi(int n,char A,char B,char C) { if(n==1) printf("%c -> %c\n",A //求年龄函数 { if(n==1) return 3; else return age(n-1)+2; } main() //主函数 { int fage; fage=age(5); printf(“第五个小朋友的年龄为%d岁\n",age); }
运行结果
案例引入
【猜年龄】
3岁
比第1个大2岁 比第2个大2岁 比第3个大2岁 比第4个大2岁
age(1)+2
age(2)+2
age(3)+2
age(4)+2
第5个小朋友几岁?
2
案例分析
递归调用定义:
一个函数在它的函数体内调用它自身称为递归调用,这种函数称为递归函数。
3
案例分析
递归函数调用定义:
一个函数在它的函数体内调用它自身称为递归调用,这种函数称为递归函数。
实例分析如下:
1、AB 2、AC 3、BC
A
C
B
8
应用实例
【汉诺塔游戏】 有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求将 所有圆盘移至C杆。移动的过程始终保持大盘在下,小盘在上的原则。
实例分析如下:
1、AC 2、AB 3、CB 4、AC 5、BA
//递归函数调用自身
main() //主函数 { int fage; fage=age(5); printf(“第五个小朋友的年龄为%d岁\n",fage); }
4
案例实现
递归函数调用定义:
一个函数在它的函数体内调用它自身称为递归调用,这种函数称为递归函数。
源程序如下:
语句编写
调用过程如下:
age(5)=age(4)+2