汉诺塔问题实验报告

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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>
结果如下:
2
6.递归应用中的 Hanoi 塔问题分析 1)Hanoi 塔问题中函数调用时系统所做工作
一个函数在运行期调用另一个函数时,在运行被调用函数之前,系 统先完成 3 件事:
1.实验目的: 通过本实验,掌握复杂性问题的分析方法,了解汉诺塔
游戏的时间复杂性和空间复杂性。 2.问题描述:
汉诺塔问题来自一个古老的传说:在世界刚被创建的时候有 一座钻石宝塔(塔 A),其上有 64 个金碟。所有碟子按从大到小的次 序从塔底堆放至塔顶。紧挨着这座塔有另外两个钻石宝塔(塔 B 和 塔 C)。从世界创始之日起,婆罗门的牧师们就一直在试图把塔 A 上的碟子移动到塔 C 上去,其间借助于塔 B 的帮助。每次只能移 动一个碟子,任何时候都不能把一个碟子放在比它小的碟子上面。 当牧师们完成任务时,世界末日也就到了。 3.算法设计思想:
归调用次数; 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) {
4
程序所花时间正比于所输出的信息行数目,而信息行的数目则等价 于盘子的移动次数。考察程序,设盘子移动次数为 moves(n),则:
moves(n)= 用迭代方法计算公式,得到结果 moves(n)=2n-1。因
此,hanoi 函数的时间复杂度为 O(2 n) 。
③ 空间复杂度
从每个塔上移走盘子时是按照 LIFO 进行,因此可以 把每个塔表示成一个堆栈。3 座塔在任何时候总共拥有的盘子都是 n 个。如果使用链表形式的堆栈,只需申请 n 个元素所需要的空间。 如果使用的是基于公式化描述的堆栈,塔 1 和塔 2 的容量都必须是 n,而塔 3 的容量是 n-1,因此所需要的空间总数为 3n-1。
Hanoi 塔问题的复杂性是以 n 为指数的函数,因此在可以接受的范 围内,只能解决 n 值比较小(n<=30)的 hanoi 问题。对于这个较 小的 n 值,堆栈在空间需求上的差别相当小,可以随意使用。
7、结论
通过对上述递归在 Hanoi 塔问题上的应用分析,我们可以得出如下 结论:
1、递归调用过程中,在程序执行之前无法知道控制这种调用栈的 规模,因为这一规模取决于递归调用的次序。在这种情况下,程序 的地址空间可能动态变化;
2)Hanoi 塔问题递归程序的复杂度分析
① 运行 hanoi 程序的时间
程序 hanoi.c 在硬件环境为赛扬 400MHz、内存 128M 的计算平台 (不同机器运行时间有一定差别)运行,可得出如下时间结果:
盘子数
时间结果
<=12 个
<=1 秒
14 个
2秒ห้องสมุดไป่ตู้
16 个
13 秒
20 个
204 秒
② 时间复杂度
①将所有的实参、返回地址等信息传递给被调用函数保存。
②为被调用函数的局部变量分配存储区;
③将控制转移到被调用函数的入口。
从被调用函数返回调用函数前,系统也应完成 3 件事:
①保存被调用函数的结果;
②释放被调用函数的数据区;
③依照被调用函数保存的返回地址将控制转移到调用函数。
当有多个函数构成嵌套调用时,按照“后调用先返回”的原则 (LIFO),上述函数之间的信息传递和控制转移必须通过“栈”来 实现,即系统将整个程序运行时所需的数据空间安排在一个栈中, 每当调用一个函数时,就为其在栈顶分配一个存储区,每当从一个 函数退出时,就释放其存储区,因此当前运行函数的数据区必在栈
3
顶。堆栈特点:LIFO,除非转移或中断,堆栈内容的存或取表现出 线性表列的性质。正是如此,程序不要求跟踪当前进入堆栈的真实 单元,而只要用一个具有自动递增或自动递减功能的堆栈计数器, 便可正确指出最后一次信息在堆栈中存放的地址。
一个递归函数的运行过程类型于多个函数的嵌套调用,只是调用函 数和被调用函数是同一个函数。因此,和每次调用相关的一个重要 的概念是递归函数运行的“层次”。假设调用该递归函数的主函数 为第 0 层,则从主函数调用递归函数为进入第 1 层;从第 i 层递归 调用本函数为进入下一层,即 i+1 层。反之,退出第 i 层递归应 返回至上一层,即 i-1 层。为了保证递归函数正确执行,系统需 设立一个“递归工作栈”,作为整个递归函数运行期间使用的数据 存储区。每一层递归所需信息构成一个“工作记录”,其中包括所 有实参、所有局部变量以及上一层的返回地址。每进入一层递归, 就产生一个新的工作记录压入栈顶。每退出一层递归,就从栈顶弹 出一个工作记录,则当前执行层的工作记录必是递归工作栈栈顶的 工作记录,称这个记录为“活动记录”,并称指示活动记录的栈顶 指针为“当前环境指针”。
对于汉诺塔问题的求解,可以通过以下三个步骤实现: (1)将塔 A 上的 n-1 个碟子借助塔 C 先移到塔 B 上。 (2)把塔 A 上剩下的一个碟子移到塔 C 上。 (3)将 n-1 个碟子从塔 B 借助于塔 A 移到塔 C 上。 4.实验步骤:
1. 用 c++ 或 c 语言设计实现汉诺塔游戏; 2. 让盘子数从 2 开始到 7 进行实验,记录程序运行时间和递
8、总结
5
缓存大小
通过对汉诺塔算法的分析让我更清楚的认识到了不同的算法对 程序性能的影响,也让我明白掌握了算法将会有助于提高软件的开 发。
6
2、递归应用于程序设计时,结构清晰、程序易读,编制和调试程 序很方便,不需要用户自行管理递归工作栈。但递归应用于计算机 时需要占用大量系统资源(包括堆栈、软中断和存贮空间等),并 消耗大量处理时间。因此,可以考虑采用并行计算进行处理,但
3、递归是串行的,其第 n 步运算依赖于第 n-1 步运算,所以在计 算机软件理论上不存在递归问题并行计算的可能性。实际上是否存 在并行递归计算有待进一步探讨。
相关文档
最新文档