《实验报告》统一格式
课程设计报告Course Project Report
报告编号 Report No: CPR-你的学号
撰写日期 Date: yyyy-mm-dd
“算法与数据结构课程设计”报告
Report on Project of Course “Algorithms and Data Structures”
姓名 Name
(计算机科学与技术专业 20nn年级 n班 学号nnnnnnnn)
成绩Grade:
河 海 大 学
“算法与数据结构课程设计”报告
Report on Project of Course “Algorithms and Data Structures”
姓名 Name
(计算机科学与技术专业 20nn年级 n班 学号nnnnnnnn)
Email: abc@abc.edu.cn
1 引言
简要说明实验背景信息。简要说明实验背景信息。简要说明实验背景信息。简要说明实验背景信息。简要说明实验背景信息。简要说明实验背景信息。简要说明实验背景信息。简要说明实验背景信息。简要说明实验背景信息。简要说明实验背景信息。
2 实验内容
【实验1.1】实验目的
实验目的与要求。实验目的与要求。实验目的与要求。实验目的与要求。实验目的与要求。实验目的与要求。实验目的与要求。实验目的与要求。
【实验1.2】设计思想(编程思路、算法流程图等)
将程序分成合理的多个模块(函数),每个模块做具体的某一事情,写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。将程序分成合理的多个模块(函数),每个模块做具体的某一事情,写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。
表1 表格标题
实验总结文字。实验总结文字。实验总结文字。实验总结文字。实验总结文字。实验总结文字。实验总结文字。实验总结文字。实验总结文字。实验总结文字。
【实验1.3】主要源代码(主要函数要有文字说明,代码注释)
将函数调用格式、参数含义、返回值描述、函数功能;函数之间的调用关系图、程序总体执行流程图;主要函数详细代码(加文档说明)。将函数调用格式、参数含义、返回值描述、函数功能;函数之间的调用关系图、程序总体执行流程图;主要函数详细代码(加文档说明)。
【实验1.4】调试与测试数据(需要调试截图,问题分析,解决办法)
出错次数、出错严重程度、解决办法摘要;至少1组测试数据。出错次数、出错严重程度、解决办法摘要;至少1组测试数据。出错次数、出错严重程度、解决办法摘要;至少1组测试数据。
……
……
3 总结与体会
……
致谢:
致谢内容 致谢内容 致谢内容 致谢内容 致谢内容 致谢内容 致谢内容。 致谢内容。 致谢内容。
附录:
1. XXXXXX
2. YYYYYY
第二篇:迷宫问题算法与数据结构课程设计
目 录
摘 要 .................................................................................... 错误!未定义书签。
前 言 ...................................................................................................................... 1
正 文 ...................................................................................................................... 3 1.
2.
3.
4.
5.
6. 采用类C语言定义相关的数据类型 .......................................................... 3 各模块的伪码算法 ...................................................................................... 3 搜索算法流程图 .......................................................................................... 6 调试分析 ...................................................................................................... 7 测试结果 ...................................................................................................... 7 源程序(带注释) .................................................................................... 10
总 结 .................................................................................................................... 16
参考文献 ................................................................................................................ 17
致 谢 .................................................................................................................... 18
附件Ⅰ 部分源程序代码 ...................................................................................... 19
摘 要
在现实生活中,会遇到很多很多关于迷宫这样很复杂、很难解决的问题的问题。如果人工去解决这些问题,会很麻烦,花很长的时间,甚至无法解决。假如用计算机去解决,可以通过手动生成迷宫,也可以通过计算机随机的产生迷宫,最终退出。而且可以很快的求解迷宫,找到从入口到出口的通路,或者当没有通路时,得出没有通路的结论。找出通路之后,会显示出通路路经,而且以图示的方式显示出通路,这样会使人一目了然的看清此迷宫的通路。迷宫是一个矩形区域,可以使用二维数组表示迷宫,这样迷宫的每一个位置都可以用其行列号来唯一指定,但是二维数组不能动态定义其大小,我们可以考虑先定义一个较大的二维数组maze[M+2][N+2],然后用它的前m行n列来存放元素,即可得到一个m×n的二维数组,这样(0,0)表示迷宫入口位置,(m-1,n-1)表示迷宫出口位置。
关键词: 迷宫;通路;二维数组;路径
1
前 言
随着社会经济的发展,信息化程度的不断深入,传统的人工求解迷宫问题已不能满足生活的需要。近几年,随着迷宫问题越来越复杂、科技也越来越发达,人们逐渐的开始用计算机求解迷宫问题。迷宫问题很复杂,但是人们又不得不去研究这个问题,因为人们的生活中需要它,离不开它。在迷宫路径的搜索过程中,首先从迷宫的入口开始,如果该位置就是迷宫出口,则已经找到了一条路径,搜索工作结束。否则搜索其上、下、左、右位置是否是障碍,若不是障碍,就移动到该位置,然后再从该位置开始搜索通往出口的路径;若是障碍就选择另一个相邻的位置,并从它开始搜索路径。为防止搜索重复出现,则将已搜索过的位置标记为2,同时保留搜索痕迹,在考虑进入下一个位置搜索之前,将当前位置保存在一个队列中,如果所有相邻的非障碍位置均被搜索过,且未找到通往出口的路径,则表明不存在从入口到出口的路径。这实现的是广度优先遍历的算法,如果找到路径,则为最短路径。
2
正 文
1. 采用类c语言定义相关的数据类型
节点类型和指针类型
迷宫矩阵类型:int maze[M+2][N+2];为方便操作使其为全局变量
迷宫中节点类型及队列类型:struct point{int row,col,predecessor} que[512]
2. 各模块的伪码算法
1、迷宫的操作
(1)手动生成迷宫
void shoudong_maze(int m,int n)
{定义i,j为循环变量
for(i<=m)
for(j<=n)
输入maze[i][j]的值
}
(2)自动生成迷宫
void zidong_maze(int m,int n)
{定义i,j为循环变量
for(i<=m)
for(j<=n)
maze[i][j]=rand()%2 //由于rand()产生的随机数是从0到
RAND_MAX,RAND_MAX是定义在stdlib.h中的,其值至少为32767),要产生从 X到Y的数,只需要这样写:k=rand()%(Y-X+1)+X;
}
(3)打印迷宫图形
void print_maze(int m,int n)
{用i,j循环变量,将maze[i][j]输出 □、■}
(4)打印迷宫路径
void result_maze(int m,int n)
3
{用i,j循环变量,将maze[i][j]输出 □、■、☆}
(5)搜索迷宫路径
①迷宫中队列入队操作
void enqueue(struct point p)
{将p放入队尾,tail++}
②迷宫中队列出队操作
struct point dequeue(struct point p)
{head++,返回que[head-1]}
③判断队列是否为空
int is_empty()
{返回head==tail的值,当队列为空时,返回0}
④访问迷宫矩阵中节点
void visit(int row,int col,int maze[41][41])
{建立新的队列节点visit_point,将其值分别赋为row,col,head-1,maze[row][col]=2,表示该节点以被访问过;调用enqueue(visit_point),将该节点入队}
⑤路径求解
void mgpath(int maze[41][41],int m,int n)
{先定义入口节点为struct point p={0,0,-1},从maze[0][0]开始访问。如果入口处即为障碍,则此迷宫无解,返回0 ,程序结束。否则访问入口节点,将入口节点标记为访问过maze[p.row][p.col]=2,调用函数enqueue(p)将该节点入队。 判断队列是否为空,当队列不为空时,则运行以下操作: { 调用dequeue()函数,将队头元素返回给p,
如果p.row==m-1且p.col==n-1,即到达出口节点,即找到了路径,结束
如果p.col+1<n且maze[p.row][p.col+1]==0,说明未到迷宫右边界,且其右方有通路,则visit(p.row,p.col+1,maze),将右边节点入队标记已访问如果p.row+1<m且maze[p.row+1][p.col]==0,说明未到迷宫下边界,且其下方有
4
通路,则visit(p.row+1,p.col,maze),将下方节点入队标记已访问
如果p.col-1>0且maze[p.row][p.col-1]==0,说明未到迷宫左边界,且其左方有通路,则visit(p.row,p.col-1,maze),将左方节点入队标记已访问
如果p.row-1>0且maze[p.row-1][p.col]==0,说明未到迷宫上边界,且其上方有通路,则visit(p.row,p.col+1,maze),将上方节点入队标记已访问
}
访问到出口(找到路径)即p.row==m-1且p.col==n-1,则逆序将
路径标记为3即maze[p.row][p.col]==3;
while(p.predecessor!=-1)
{p=queue[p.predecessor];
maze[p.row][p.col]==3;}
最后将路径图形打印出来。
2.菜单选择
while(cycle!=(-1))
☆ 手动生成迷宫 请按:1
☆ 自动生成迷宫 请按:2
☆ 退出 请按:3
scanf("%d",&i);
switch(i)
{ case 1:请输入行列数(如果超出预设范围则提示重新输入) shoudong_maze(m,n);
print_maze(m,n); mgpath(maze,m,n); if(X!=0) result_maze(m,n);
case 2 :请输入行列数(如果超出预设范围则提示重新输入) zidong_maze(m,n);
print_maze(m,n);
5
mgpath(maze,m,n);
if(X!=0) result_maze(m,n);
case 3:cycle=(-1); break; }
3. 搜索算法流程图
6
4. 调试分析
a、调试中遇到的问题及对问题的解决方法
在调试过程中,刚开始系统自动生成的迷宫并不是随机的,而是每次生成的都一样;求解时,不能正确的得到结果,有时还会求错;输出的路径是乱的,而不是按顺序显示。
出现上述问题之后,经过和同学的探讨研究,重写随机函数、修改语句、调换语句的位置等一次一次的试验,最终问题才得以解决。
在调试过程中,首先使用的是栈进行存储,但是产生的路径是多条或不是最短路径,所以通过算法比较,改用此算法
b、算法的时间复杂度和空间复杂度
该算法的运行时间和使用系统栈所占有的存储空间与迷宫的大小成正比,迷宫长为m,宽为n,在最好情况下的时间和空间复杂度均为O(m+n),在最差情况下均为O(m*n),平均情况在它们之间
5. 测试结果
进入系统主菜单:
7
选择1,即手动生成迷宫,及生成后有通路的求解结果:
选择2,系统自动生成迷宫,此迷宫无通路:
8
选择2,系统自动生成迷宫,生成的有解迷宫的解:
9
选择3,退出系统:
6. 源程序(带注释)
#include"stdlib.h" #include"stdio.h" #define N 39 #define M 39 int X; int maze[N+2][M+2]; struct point{ int row,col,predecessor; }queue[512]; int head=0,tail=0; void shoudong_maze(int m,int n){ //手动生成迷宫 } void zidong_maze(int m,int n){ //自动生成迷宫 int i,j;
10 int i,j; printf("\n\n"); printf("请按行输入迷宫,0表示通路,1表示障碍:\n\n"); for(i=0;i<m;i++) for(j=0;j<n;j++) scanf("%d",&maze[i][j]);
printf("\n迷宫生成中……\n\n"); system("pause"); for(i=0;i<m;i++) for(j=0;j<n;j++) maze[i][j]=rand()%2; //自动生成迷宫的随机函数 //由于rand()产生的随机数是从0到RAND_MAX //RAND_MAX是定义在stdlib.h中的,其值至少为32767) //要产生从X到Y的数,只需要这样写:k=rand()%(Y-X+1)+X; } void print_maze(int m,int n){ //打印生成的迷宫 } void result_maze(int m,int n){ int i,j; printf("迷宫通路(用☆表示)如下所示:\n\t"); for(i=0;i<m;i++) {printf("\n"); for(j=0;j<n;j++) {if(maze[i][j]==0||maze[i][j]==2) printf("□"); if(maze[i][j]==1) printf("■");
11 int i,j; printf("\n迷宫生成结果如下:\n\n"); printf("迷宫入口\n"); printf("↓"); for(i=0;i<m;i++) {printf("\n"); for(j=0;j<n;j++) {if(maze[i][j]==0) printf("□"); if(maze[i][j]==1) printf("■");} } printf("→迷宫出口\n");
} void enqueue(struct point p){ } struct point dequeue(){ } int is_empty(){ } void visit(int row,int col,int maze[41][41]){ } int mgpath(int maze[41][41],int m,int n){ X=1; struct point p={0,0,-1}; if(maze[p.row][p.col]==1) struct point visit_point={row,col,head-1}; maze[row][col]=2; enqueue(visit_point); return head==tail; head++; return queue[head-1]; queue[tail]=p; tail++; if(maze[i][j]==3) printf("☆"); } }
{printf("\n===============================================\n"); printf("此迷宫无解\n\n");X=0;return 0;}
maze[p.row][p.col]=2; enqueue(p); while(!is_empty()) {p=dequeue();
12
{printf("\n==================================================== if((p.row==m-1)&&(p.col==n-1)) break; if((p.col+1<n)&&(maze[p.row][p.col+1]==0)) visit(p.row,p.col+1,maze); if((p.row+1<m)&&(maze[p.row+1][p.col]==0)) visit(p.row+1,p.col,maze); if((p.col-1>=0)&&(maze[p.row][p.col-1]==0)) visit(p.row,p.col-1,maze); if((p.row-1>=0)&&(maze[p.row-1][p.col]==0)) visit(p.row-1,p.col,maze); } if(p.row==m-1&&p.col==n-1) ==============\n");
printf("迷宫路径为:\n"); printf("(%d,%d)\n",p.row,p.col); maze[p.row][p.col]=3; while(p.predecessor!=-1) {p=queue[p.predecessor]; printf("(%d,%d)\n",p.row,p.col); maze[p.row][p.col]=3; } } else
{printf("\n=============================================================\n");
} void main() {int i,m,n,cycle=0; while(cycle!=(-1)) //主菜单 {
13 printf("此迷宫无解!\n\n");X=0;} return 0;
printf("*************************************************************\n"); printf(" 欢迎进入迷宫求解系统\n");
printf(" 设计者:兰理工计算机4班赵永刚 \n");
printf("********************************************************************************\n");
printf(" ☆ 手动生成迷宫 请按:1\n"); printf(" ☆ 自动生成迷宫 请按:2\n"); printf(" ☆ 退出 请按:3\n\n");
printf("********************************************************************************\n");
printf("\n"); printf("请选择你的操作:\n"); scanf("%d",&i); switch(i) {case 1:printf("\n请输入行数:");scanf("%d",&m); printf("\n"); printf("请输入列数:");scanf("%d",&n); while((m<=0||m>39)||(n<=0||n>39)) {printf("\n抱歉,你输入的行列数超出预设范围(0-39,0-39),请重新输入:\n\n");
printf("请输入行数:");scanf("%d",&m); printf("\n"); printf("请输入列数:");scanf("%d",&n); } shoudong_maze(m,n); print_maze(m,n); mgpath(maze,m,n);
14
if(X!=0) result_maze(m,n); printf("\n\nPress Enter Contiue!\n");getchar();while(getchar()!='\n');break;
case 2:printf("\n请输入行数:");scanf("%d",&m); printf("\n"); printf("请输入列数:");scanf("%d",&n); while((m<=0||m>39)||(n<=0||n>39)) {printf("\n抱歉,你输入的行列数超出预设范围(0-39,0-39),请重新输入:\n\n");
printf("请输入行数:");scanf("%d",&m); printf("\n"); printf("请输入列数:");scanf("%d",&n); } zidong_maze(m,n); print_maze(m,n); mgpath(maze,m,n); if(X!=0) result_maze(m,n); printf("\n\nPress Enter Contiue!\n");getchar();while(getchar()!='\n');break;
case 3:cycle=(-1);break; default:printf("\n");printf("你的输入有误!\n"); printf("\nPress Enter Contiue!\n");getchar();while(getchar()!='\n');break; } } }
15
总 结
通过这段时间的课程设计,本人对计算机的应用,数据结构的作用以及C语言的使用都有了更深的了解。尤其是C语言的进步让我深刻的感受到任何所学的知识都需要实践,没有实践就无法真正理解这些知识以及掌握它们,使其成为自己的财富。在理论学习和上机实践的各个环节中,通过自主学习和请教老师,我收获了不少。当然也遇到不少的问题,也正是因为这些问题引发的思考给我带了收获。从当初不喜欢上机写程序到现在能主动写程序,从当初拿着程序不只如何下手到现在知道如何分析问题,如何用专业知识解决实际问题的转变,我发现无论是专业知识还是动手能力,自己都有很大程度的提高。在这段时间里,我对for、while等的循环函数用法更加熟悉,逐渐形成了较好的编程习惯。在老师的指导帮助下,同学们课余时间的讨论中,这些问题都一一得到了解决。在程序的调试能力上,无形中得到了许多的提高。例如:头文件的使用,变量和数组的范围问题,定义变量时出现的问题等等。
在实际的上机操作过程中,不仅是让我们了解数据结构的理论知识,更重要的是培养解决实际问题的能力,所以相信通过此次实习可以提高我们分析设计能力和编程能力,为后续课程的学习及实践打下良好的基础。
在这次短短的课程实践里,我们得到了卢鹏丽老师的关心和帮助。她给了我们很多的信息,与我们一起探讨问题,询问我们遇到了哪些问题并耐心给予指导。当我们遇到技术上难以解决的问题时,她就会指导我们解决问题,她把自己多年来积累的经验教授给我们,使我们顺利地完成了课程实践任务。时间过得真快,大学生活不知不觉就走过了一年,一年的大学学习和课程实践阶段的提高,使我们本身知识得到提高的同时,也增强了我们对未来工作的信心,我们相信自己未来的学习更使我们有能力胜任将来的工作。
16
参考文献
1 严蔚敏,吴伟民.《数据结构(C语言版)》.清华大学出版社. 2 严蔚敏,吴伟民.《数据结构题集(C语言版)》.清华大学出版社.
3 《DATA STRUCTURE WITH C++》. William Ford,William Topp .清华大学出版社(影印版).
4 谭浩强.《c语言程序设计》. 清华大学出版社.
5.数据结构与算法分析(Java版) , A Practical Introduction to Data 张铭,刘晓丹译 电子工业出版社 2001 年1月
17
致 谢
在这样的一个程序设计中,靠一个人的单打独斗是不可能完成的。在这次设计过程中,在开始的构思、设想,源代码编写时的提示,上机时精心的指点,有了老师和舍友以及身边同学的指导、意见和帮助,最终才完成了这个迷宫求解问题系统的设计与实现。所以在这里要对以上老师及同学表示感谢,非常感谢他们的帮助。而且在这次课程设计中我学习到了很多很多。
18
附件Ⅰ 部分源程序代码
void main()
{int i,m,n,cycle=0; while(cycle!=(-1)) {
printf("*************************************************************\n"); printf(" 欢迎进入迷宫求解系统\n");
printf(" 设计者:兰理工计算机4班赵永刚 \n");
printf("********************************************************************************\n");
printf(" ☆ 手动生成迷宫 请按:1\n"); printf(" ☆ 自动生成迷宫 请按:2\n"); printf(" ☆ 退出 请按:3\n\n"); printf("********************************************************************************\n");
printf("\n"); printf("请选择你的操作:\n"); scanf("%d",&i); switch(i) {case 1:printf("\n请输入行数:");scanf("%d",&m); printf("\n"); printf("请输入列数:");scanf("%d",&n); while((m<=0||m>39)||(n<=0||n>39)) {printf("\n抱歉,你输入的行列数超出预设范围(0-39,0-39),请重新输入:\n\n");
printf("请输入行数:");scanf("%d",&m); printf("\n");
19
printf("请输入列数:");scanf("%d",&n); } shoudong_maze(m,n); print_maze(m,n); mgpath(maze,m,n); if(X!=0) result_maze(m,n); printf("\n\nPress Enter Contiue!\n");getchar();while(getchar()!='\n');break;
case 2:printf("\n请输入行数:");scanf("%d",&m); printf("\n"); printf("请输入列数:");scanf("%d",&n); while((m<=0||m>39)||(n<=0||n>39)) {printf("\n抱歉,你输入的行列数超出预设范围(0-39,0-39),请重新输入:\n\n");
printf("请输入行数:");scanf("%d",&m); printf("\n"); printf("请输入列数:");scanf("%d",&n); } zidong_maze(m,n); print_maze(m,n); mgpath(maze,m,n); if(X!=0) result_maze(m,n); printf("\n\nPress Enter Contiue!\n");getchar();while(getchar()!='\n');break;
}
20 case 3:cycle=(-1);break; default:printf("\n");printf("你的输入有误!\n"); printf("\nPress Enter Contiue!\n");getchar();while(getchar()!='\n');break; } }