数据结构程序的设计课题.docx

上传人:b****7 文档编号:10278905 上传时间:2023-02-09 格式:DOCX 页数:29 大小:92.78KB
下载 相关 举报
数据结构程序的设计课题.docx_第1页
第1页 / 共29页
数据结构程序的设计课题.docx_第2页
第2页 / 共29页
数据结构程序的设计课题.docx_第3页
第3页 / 共29页
数据结构程序的设计课题.docx_第4页
第4页 / 共29页
数据结构程序的设计课题.docx_第5页
第5页 / 共29页
点击查看更多>>
下载资源
资源描述

数据结构程序的设计课题.docx

《数据结构程序的设计课题.docx》由会员分享,可在线阅读,更多相关《数据结构程序的设计课题.docx(29页珍藏版)》请在冰豆网上搜索。

数据结构程序的设计课题.docx

数据结构程序的设计课题

师学院

工科课程设计-《数据结构》

题目:

迷宫问题(栈)

学号:

1445013914450132

姓名:

鲁向阳肖吟月

班级:

物联网班(1405)

指导教师:

王杰老师

日期:

2016年6月

 

1概述

1.1课程设计目的

本次课程设计是迷宫求解问题,主要是模拟从入口到出口的通路。

程序中的数据采取的是“栈”作为数据的逻辑结构,并且使用链式存储结构,即是实现一个以链表作存储结构的栈类型。

本课程设计实现了链栈的建立,入栈,出栈,判断栈是否为空的方法,关键的是迷宫通路路径的“穷举求解”和递归求解的方法。

1.2开发环境

具有Intel酷睿i3处理器且满足以下要求的计算机:

4GB存,500GB硬盘;安装VisualC++6.0。

1.3任务分配

两人一起查找相关资料,整合并进行探讨。

其中一人通过查找的资料先行拟定文件的大纲,初步定稿后,然后再由另一个人进行进一步加工,细化,最后两人一起核实文件,进行进一步的升华,最终完成该任务。

2需求分析

2.1题目容

以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。

设计一个程序,对任意设定的迷宫,求出一条从入口到出口的通路,或得出没有通路的结论。

2.2设计思想说明

计算机解迷宫通常用的是“穷举求解”方法,首先从迷宫的入口开始,如果该位置就是迷宫出口,则已经找到了一条路径,搜索工作结束。

否则从入口出发,顺着某个方向进行探索,若能走通,则继续往前进,否则沿着原路退回,换一个方向继续探索,直至出口位置,求得一条通路。

假如所有可能的通路都探索到而未能到达出口,则所设的迷宫没有通路。

可以用二维数组存储迷宫数据,通常设定入口点的下标为(1,1),出口点的下标为(n,n)。

为处理方便起见,可在迷宫的四周加一圈障碍。

对于迷宫中任一位置均可约定有东、南、西、北四个方向可通。

要实现上述算法,需要用到栈的思想。

栈里面压的是走过的路径,若遇到死路,则将该位置在栈的顶层)弹出,再进行下一次判断;若遇到通路,则将该位置压栈并进行下一次判断。

如此反复循环,直到程序结束。

此时,若迷宫有通路,则栈中存储的是迷宫通路坐标的倒序排列,再把所有坐标顺序排列好后,即可得到正确的迷宫通路。

2.3数据结构设计

(1)以一个m*n的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍。

迷宫的四周有一圈障碍。

(2)程序输出的结果以三元组(i,j,di)的形式输出,其中:

(i,j)指示迷宫中的一个坐标,di表示走到下一坐标的方向,di的取值为0、1、2、3分别表示北、东、南、西。

(3)若设定的迷宫存在通路,则以方阵形式将迷宫及其通路输出到标准输出文件上,对于迷宫中的每个方块,有上下左右4个方块相邻,第i行第j列的当前方块的位置记为(i,j),规定上方方块为方位0,并按顺时针方向递增编号。

在试探过程中,假设按从方位0到方位3的顺序查找下一个可走的方块。

(4)先将入口进栈(其初始方位设置为-1),在栈不空时循环:

取栈顶方块(不退栈),若该方块是出口,则输出栈中所有方块即为路径,否则,找下一个可走的相邻方块,若不存在这样的方块,说明当前路径不可能走通,则回溯。

也就是恢复当前方块为0后退栈;若存在这样的方块,则将这个可走的相邻方块进栈(其初始方位设置为-1)。

3算法的设计

3.1定义坐标(X,Y)

#include

#include

usingnamespacestd;

structCoor

{

introw;

intcolumn;

intdirection;

};

3.2定义方向

structMove

{

introw;

intcolumn;

};

3.3定义/链表结点

structLinkNode

{

Coordata;

LinkNode*next;

};

3.4定义栈

classstack

{

private:

LinkNode*top;

public:

stack();

~stack();

voidPush(Coordata);

CoorPop();

CoorGetPop();

voidClear();

boolIsEmpty();

};

3.5定义迷宫定义移动的4个方向

Movemove[4]={{0,1},{1,0},{0,-1},{-1,0}};

6、几个函数功能的描述:

stack();//构造函数,置空栈

~stack();//析构函数

voidPush(Coordata);//把元素data压入栈中

CoorPop();//使栈顶元素出栈

CoorGetPop();//取出栈顶元素

voidClear();//把栈清空

boolIsEmpty();//判断栈是否为空

boolMazepath(int**maze,intm,intn);

//寻找迷宫maze中从(0,0)到(m,n)的路径

//到则返回true,否则返回false

voidPrintPath(stackp);//输出迷宫的路径

voidPrintPath2(intm,intn,stackp,int**maze);//输出路径

voidRestore(int**maze,intm,intn);//恢复迷

4各模块的伪码算法

4.1根据输入产生一个8*8的迷宫

m=a;

n=b;

maze=newint*[m+2];//申请长度等于行数加2的二级指针

for(i=0;i

{

maze[i]=newint[n+2];

}

for(i=1;i<=m;i++)

for(j=1;j<=n;j++)

cin>>maze[i][j];

cout<<"是否保存新迷宫?

\n";

cout<<"用Y或y表示保存、N或n表示不保存\n";

charchoose;

cin>>choose;

if(choose=='Y'||choose=='y')

{

charch;

ofstreamfop("Newtest.txt");

for(i=1;i<=m;i++)

{

for(j=1;j<=n;j++)

{

ch='0'+maze[i][j];

fop<

}

fop<

flush(cout);

}

fop.close();

}

}

//给迷宫的四周加一堵墙,即把迷宫四周定义为1

for(i=0;i

maze[i][0]=maze[i][n+1]=1;

for(i=0;i

maze[0][i]=maze[m+1][i]=1;

for(intp=0;p

{

for(intq=0;q<=n+2;++q)

{

if(maze[p][q]==0)

cout<<"■";

if(maze[p][q]>=1)

cout<<"□";

}

cout<

}

returnmaze;//返回存贮迷宫的二维指针maze

4.2探索路径函数

boolMazepath(int**maze,intm,intn)

//寻找迷宫maze中从(0,0)到(m,n)的路径

//到则返回true,否则返回false

{

stackq,p;//定义栈p、q,分别存探索迷宫的存储和路径过程

CoorTemp1,Temp2;

introw,column,loop;

Temp1.row=1;

Temp1.column=1;

q.Push(Temp1);//将入口位置入栈

p.Push(Temp1);

maze[1][1]=8;//标志入口位置已到达过

while(!

q.IsEmpty())//栈q非空,则反复探索

{

Temp2=q.GetPop();//获取栈顶元素

if(!

(p.GetPop().row==q.GetPop().row&&p.GetPop().column==q.GetPop().column))

p.Push(Temp2);

//如果有新位置入栈,则把上一个探索的位置存入栈p

for(loop=0;loop<4;loop++)//探索当前位置的4个相邻位置

{

row=Temp2.row+move[loop].row;//计算出新位置x位置值

column=Temp2.column+move[loop].column;//计算出新位置y位置值

if(maze[row][column]==0)//判断新位置是否可达

{

Temp1.row=row;

Temp1.column=column;

maze[row][column]=8;//标志新位置已到达过

q.Push(Temp1);//新位置入栈

}

if((row==(m))&&(column==(n)))//成功到达出口

{

Temp1.row=m;

Temp1.column=n;

Temp1.direction=0;

p.Push(Temp1);//把最后一个位置入栈

charchoose;

cout<<"请选择以坐标形式(row,column,direction)输出迷宫选

(1)或以方阵形式输出迷宫选

(2):

";

cin>>choose;

if(choose=='1')

{

PrintPath(p);//坐标显示输出

Restore(maze,m,n);

}

else

{

PrintPath2(m,n,p,maze);//矩阵显示输出

Restore(maze,m,n);

}

return1;//表示成功找到路径

}

}

if(p.GetPop().row==q.GetPop().row&&p.GetPop().column==q.GetPop().column)

//如果没有新位置入栈,则返回到上一个位置

{

p.Pop();

q.Pop();

}

}

return0;//表示查找失败,即迷宫无路经

}

4.3输出迷宫

voidPrintPath(stackp)//输出路径

{

cout<<"迷宫的路径为\n";

cout<<"括号的容分别表示为(行坐标,列坐标,数字化方向,方向)\n";

stackt;//定义一个栈,按从入口到出口存取路径

inta,b;

Coordata;

LinkNode*temp;

temp=newLinkNode;//申请空间

temp->data=p.Pop();//取栈p的顶点元素,即第一个位置

t.Push(temp->data);//第一个位置入栈t

deletetemp;//释放空间

while(!

p.IsEmpty())//栈p非空,则反复转移

{

temp=newLinkNode;

temp->data=p.Pop();//获取下一个位置

//得到行走方向

a=t.GetPop().row-temp->data.row;//行坐标方向

b=t.GetPop().column-temp->data.column;//列坐标方向

if(a==1)temp->data.direction=1;//方向向下,用1表示

elseif(b==1)temp->data.direction=2;//方向向右,用2表示

elseif(a==-1)temp->data.direction=3;//方向向上,用3表示

elseif(b==-1)temp->data.direction=4;//方向向左,用4表示

t.Push(temp->data);//把新位置入栈

deletetemp;

}

cout<<"坐标(row,column,direction)中x在指向当前位置所在的行数,y指向当前位置所在的列数,";

cout<<"direction表示下一位置走向。

"<

//输出路径,包括行坐标,列坐标,下一个位置方向

while(!

t.IsEmpty())//栈非空,继续输出

{

data=t.Pop();

cout<<'('<

switch(data.direction)//输出相应的方向

{

case1:

cout<<"↓)\n";break;

case2:

cout<<"→)\n";break;

case3:

cout<<"↑)\n";break;

case4:

cout<<"←)\n";break;

case0:

cout<<")\n";break;

}

}

}

voidPrintPath2(intm,intn,stackp,int**maze)//输出路径

{

cout<<"迷宫的路径为\n";

for(inti=0;i

{

for(intj=0;j

cout<

cout<

}

}

5函数的调用关系图

6测试结果

6.1自动生成迷宫运行情况

(1)选择生成迷宫输入1如下图所示

(2)选择以坐标形式输出迷宫:

7心得体会

通过这段时间的课程设计,本人对计算机的应用,数据结构的作用以及C语言的使用都有了更深的了解。

尤其是C语言的进步让我深刻的感受到任何所学的知识都需要实践,没有实践就无法真正理解这些知识以及掌握它们,使其成为自己的财富。

在设计此程序时,刚开始感到比较迷茫,然后一步步分析,试着写出基本的算法,思路渐渐清晰,最后完成程序。

当然也遇到不少的问题,也正是因为这些问题引发的思考给我带了收获。

在遇到描写迷宫路径的算法时,我感到有些困难,后来经过一步步分析和借鉴书本上的穷举求解的算法,最后把算法写出来。

在利用递归方法求路径时花费了我很长时间,由于本人对递归方面的知识运用较少,导致我不熟悉它的用法,但最终还是通过询问同学、查找书本和上网了解关于递归方面的知识写出来了。

这次课程设计让我更加深入了解很多方面的知识,如链结构的栈类型及其基本操作,数组的运用等等。

在程序的编写中不要一味的模仿,要自己去摸索,只有带着问题反复实践,才能熟练地掌握和运用。

在实际的上机操作过程中,不仅是让我们了解数据结构的理论知识,更重要的是培养解决实际问题的能力,所以相信通过此次实习可以提高我们分析设计能力和编程能力,为后续课程的学习及实践打下良好的基础。

 

参考文献

[1]严蔚敏、吴伟民:

《数据结构(C语言版)》[M],清华大学2007年版

[2]谭浩强:

《C语言设计(第三版)》[M],清华大学2005年版

[3]衍龙、林瑞仲、徐慧:

《C语言实例解析精粹(第二版)》[M],人民邮电

附录

#include

#include

usingnamespacestd;

structCoor//定义描当前位置的结构类型

{

introw;

intcolumn;

intdirection;

};

structMove//定义下一个位置的方向

{

introw;

intcolumn;

};

structLinkNode//链表结点

{

Coordata;

LinkNode*next;

};

//定义栈

classstack

{

private:

LinkNode*top;

public:

stack();//构造函数,置空栈

~stack();//析构函数

voidPush(Coordata);//把元素data压入栈中

CoorPop();//使栈顶元素出栈

CoorGetPop();//取出栈顶元素

voidClear();//把栈清空

boolIsEmpty();//判断栈是否为空

};

stack:

:

stack()//构造函数,置空栈

{

top=NULL;

}

stack:

:

~stack()//析构函数

{

}

voidstack:

:

Push(Coorx)//把元素data压入栈中

{

LinkNode*TempNode;

TempNode=newLinkNode;

TempNode->data=x;

TempNode->next=top;

top=TempNode;

}

Coorstack:

:

Pop()//使栈顶元素出栈

{

CoorTemp;

LinkNode*TempNode;

TempNode=top;

top=top->next;

Temp=TempNode->data;

deleteTempNode;

returnTemp;

}

Coorstack:

:

GetPop()//取出栈顶元素

{

returntop->data;

}

voidstack:

:

Clear()//把栈清空

{

top=NULL;

}

boolstack:

:

IsEmpty()

{

if(top==NULL)

returntrue;

else

returnfalse;

}

Movemove[4]={{0,1},{1,0},{0,-1},{-1,0}};//定义移动的4个方向

boolMazepath(int**maze,intm,intn);

//寻找迷宫maze中从(0,0)到(m,n)的路径

//到则返回true,否则返回false

voidPrintPath(stackp);//输出迷宫的路径

voidPrintPath2(intm,intn,stackp,int**maze);//输出路径

voidRestore(int**maze,intm,intn);//恢复迷宫

int**GetMaze(int&m,int&n);//获取迷宫(可从文件中读取,也可输入)

//返回存取迷宫的二维指针

intmain()

{

system("colorf5");

intm=0,n=0;

int**maze;//定义二维指针存取迷宫

cout<<"\n\t\t****************欢迎使用迷宫模拟程序*************"<

cout<<"\t\t14级计算机物联网班"<

cout<<"\t\t鲁向阳肖吟月"<

cout<<"\t\t学号:

1445013914450132"<

maze=GetMaze(m,n);//调用GetMaze(int&m,int&n)函数,得到迷宫

if(Mazepath(maze,m,n))//调用Mazepath(int**maze,intm,intn)函数获取路径

cout<<"迷宫路径探索成功!

\n";

elsecout<<"路径不存在!

\n";

return0;

}

int**GetMaze(int&m,int&n)

//获取迷宫(可从文件中读取,也可输入)

//返回存取迷宫的二维指针

{

int**maze;

inti=0,j=0;

charChoose;//定义一个标志,选择读取文件或直接输入,获取迷宫

cout<<"请选择生成

(1)或键盘输入

(2):

";

cin>>Choose;

if(Choose=='1')//当标志Choose为‘1’时,读取文件

{

cout<<"生成迷宫如下:

\n";

charch;//定义一个字符,读取文件中的容

i=0,j=0;

//首先得到文件中数字字符的数目,并得到迷宫的长和宽

ifstreamfip("test.txt");

//定义一个文件对象,并打开文件“test.txt”

while(fip.get(ch))//从读取文件中容(一个个字符)

{

if(ch>='0'&&ch<='9')//获取文件中的数字字符

{

j++;//如果是字符,列就加1

}

if(ch=='\n')

{

i++;//如果是换行,就行加1

n=j;//得到宽,即列数

j=0;

}

}

fip.close();//读取文件结束

m=i;//得到长即行数

maze=newint*[m+2];//申请长度等于行数加2的二级指针

for(i=0;i

{

maze[i]=newint[n+2];

}

i=j=1;

ifstreamfip2("test.txt");//重新读取文件,以得到容

while(fip2.get(ch))

{

if(ch>='0'&&ch<='9')

{

maze[i][j]=ch-'0';//把数字字符转化为数字,并存到指针里

cout<

j++;

}

if(ch=='\n')//遇到换行,指针也相应换行

{

cout<

i++;

j=1;

}

}

fip2.close();//读取结束

cout<

}

else//Choose=2,输入迷宫

{

 

cout<<"请输入迷宫的行数和列数:

(中间用空格键分开)";

inta,b;

cin>>a>>b;

cout<<"请输入迷宫容:

(0表示通路,1表示不连通。

中间用空格键分开)\n";

m=a;

n=b;

maze=newint*[m+2];//申请长度等于行

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1