数据结构与算法课程设计报告.docx

上传人:b****3 文档编号:3696593 上传时间:2022-11-24 格式:DOCX 页数:14 大小:97.79KB
下载 相关 举报
数据结构与算法课程设计报告.docx_第1页
第1页 / 共14页
数据结构与算法课程设计报告.docx_第2页
第2页 / 共14页
数据结构与算法课程设计报告.docx_第3页
第3页 / 共14页
数据结构与算法课程设计报告.docx_第4页
第4页 / 共14页
数据结构与算法课程设计报告.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

数据结构与算法课程设计报告.docx

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

数据结构与算法课程设计报告.docx

数据结构与算法课程设计报告

 

合肥学院

计算机科学与技术系

 

课程设计报告

2011~2012学年第二学期

 

课程

数据结构与算法

课程设计名称

骑士游历

学生姓名

王晓龙

学号

1004011026

专业班级

10级计本一班

指导教师

李红陈艳平

2012年6月10日

题目:

名称:

骑士游历

内容:

给你一个8*8的棋盘,骑士的开始位置,结束位置,让你求得骑士从开始位置开始走到结束位置需要最小的步数是多少?

(注意,骑士走日字)

要求:

(1)输入:

输入包含多组数据,每一行都是一组开始位置和结束位置,位置由两个字符组成,一个是小写字母(a-h),一个是数字(1-8),起始位置结束位置由一个空格隔开.

(2)输出:

输出从起始位置到结束位置,骑士所要走过的最小的步数.

(3)所设计的数据结构应尽可能节省存储空间。

(4)程序的运行时间应尽可能少。

一、问题分析和任务定义

此程序需要完成如下要求:

给你一个8*8的棋盘,骑士的开始位置,结束位置,让你求得骑士从开始位置开始走到结束位置需要最小的步数是多少?

(注意,骑士走日字)

实现本程序需要解决以下几个问题:

1、如何表示8*8的棋盘,确定棋盘上各点的位置。

2、马在棋盘上的各种行走方法怎样来表示,行走过程如何实现。

3、如何表示位置由两个字符组成,一个是小写字母(a-h),一个是数字(1-8)。

4、如何找到一条满足条件的路径。

5、如何确定这条路径是最短的。

本问题的关键和难点是如何根据骑士的走法规则,找出一条最短路径。

h

g

f

e

d

c

b

a|0

1

2

3

4

5

6

7

图1:

8*8的棋盘

如图,建立如上的坐标系,于是每个点的位置就可以用一个有序数对来表示。

如:

(a,3),(b,6),(h,2)。

对于任意一点的马最多有8中走法可以选择。

根据马行走后行列坐标数值大小的增加和减少情况的变化,用有序数组对来表示其走法。

staticintbx[8]={2,1,-1,-2,-2,-1,1,2};

staticintby[8]={1,2,2,1,-1,-2,-2,-1};

其中,bx数组与by数组下标相同的变量表示一种走法。

骑士在棋盘中的位置可由结构体类型

typedefstruct

{

intn,m;//n记录行数,m记录列数

intch;

}node;

来表示。

对于骑士的起始与终点位置可由有序对(x0,y0),(x1,y1)来表示。

另外建立一个队列,

typedefstruct//定义顺序队列类型

{

nodedata[maxlen];

intfront;

intrear;

}Sequeue;

把骑士从起点到终点的每一步入队,前一步出对。

 

二、概要设计与数据结构选择

对于所提出的关键问题,即找出从起点到终点的最短步数,这里所用到的方法是遍历起点与终点的所有路径,记录下其步数,然后比较其中最小的步数,即为最短步数。

1、输入起点和终点的坐标,起点先入对;

2、按照上述的8走法分别走一步,如果到达终点,计步器加一,如果未到终点,计步器加一并入对;(所有走法均入队)

3、出对,以步骤2中的如对顺序分别把其作为新起点,重复步骤2;

4、判断是否对空,对空则以走过全部路径,对未空,重复步骤3;对空,转到步骤5;

5、比较每种路径的步数,选出最小的数值,即为最小步数。

以上操作相当于对于一棵8个结点的完全树进行遍历,查找满足条件的结点,并找出这些结点中结点高度最低的结点。

以上过程可由树来表示。

树如图2:

 

 

…………

 

…………………………

………………………………

 

图2:

骑士游历的树结构

如图3,先找到起点,即根节点,并进行入队操作。

由起点逐次访问起点的各个子树的根节点,比较是否等于终点的坐标,若相等,则保存路径长度;若不相等,则把不相等的子树的根节点进行入队操作。

访问完所有子树的根节点后,进行一次出队操作;即把根节点出队。

此后顺次访问队头节点的子树的根节点,即顺次访问根节点的子树的根节点的各个子树的根节点,比较是否等于终点的坐标,若相等,则保存路径长度;若不相等,则把不相等的子树的根节点进行入队操作。

直到队为空为止。

访问顺序如下:

…………

 

图3:

游历的访问顺序

 

数据结构如下:

typedefstruct//骑士位置结构体

{

intn,m;//n记录行数,m记录列数

intch;

}node;

typedefstruct//顺序队列类型结构体

{

nodedata[maxlen];

intfront;

intrear;

}Sequeue;

 

 

 

 

 

图4:

详细设计流程图

 

三、详细设计和编码

首先,对于在问题分析和任务定义中所提出的问题逐个进行解决。

定义棋盘和走法,并对其进行初始化。

intway[8][8]表示棋盘每一点的位置,例如,way[2][2]表示第三行,第三列的坐标,way[3][6]表示第四行,第七列的坐标。

因为在本实验中并没有要求骑士行走的路径,所以棋盘可不显示的定义。

对于走法,我们前面已经提到了,对于马在棋盘中的任意位置,最多有8种走法,用有序数对表示即:

(2,1),(2,-1)(1,2),(1.-2)(-2,1),(-2,-1),(-1,2),(-1,-2)。

故,我们可以做如下定义:

根据马行走后行列坐标数值大小的增加和减少情况的变化,用有序数组对来表示其走法。

staticintbx[8]={2,1,-1,-2,-2,-1,1,2};

staticintby[8]={1,2,2,1,-1,-2,-2,-1};

其中,bx数组与by数组下标相同的变量表示一种走法。

所以在骑士的行走过程中,只要让骑士的位置即坐标加上或减去上述8中走法的数组表示。

对于骑士的起点和终点的位置表示,根据要求位置由两个字符组成,一个是小写字母(a-h),一个是数字(1-8)。

所以有如下的表示方法:

intx0,y0,x1,y1;charxa,xb;x0=xa-‘a’;x1=xb-‘a’;

其中,x0、y0表示起点坐标,x1、y1表示终点坐标,输入的xa,xb为字符,减去‘a’,便可转换成数字。

这样便可以把输入的字符坐标转换成用数字表示的坐标。

在得到骑士的起点终点坐标之后,便可以把起点入队,入队函数如下所示:

voidadd(Sequeue*S,intx,inty,intz)//入队函数

{

if(S->rearrear>=0)

{

S->rear++;

S->data[S->rear].n=x;

S->data[S->rear].m=y;

S->data[S->rear].ch=z;

}

elseprintf("error\n");

}

这里的参数x,y,z分别表示行坐标,列坐标,和到达该坐标从起点所走的步数。

它们的值分别保存在队列的n,m,ch中。

在对起点进行入队之后,便可进行运动了,即骑士可以按规则(8种走法)走向下一位置。

此后,在一个while循环中进行如下的操作,while循环的条件为:

S->frontrear,保证在队列不为空的情况下进行循环。

对于骑士的8种走法,可以通过for(i=0;i<8;i++)循环进行逐个试探。

这里可以定义两个证型变量x3、y3;用以存放骑士走一步后的位置,即坐标。

则有如下定义:

x3=bx[i]+x0;y3=by[i]+y0;

又由实际情况可知,x3、y3应该满足x3、y3同时大于等于0且小于8;在此时设置标记数组step[maxlen][maxlen]=0;标记数组用以标记该位置是否已经走过,走过则置1;所以x3、y3还应满足step[x3][y3]==0;即(x3,y3)这个位置还未走过。

若满足以上条件,则可以定义node*p;并为其申请内存空间。

有如下一段程序:

p=(node*)malloc(sizeof(node));

p->ch=S->data[S->front+1].ch+1;

p->n=x3;

p->m=y3;

step[x3][y3]=1;

把(x3,y3)的值放入指针p指向的空间的(n,m)中,用以保存此位置;因为ch存放的是从起点到该位置所走的步数,故p->ch=S->data[S->front+1].ch+1;即它表示的意思是从起点x3、y3所走的步数。

此时并把x3y3的标记置为1,说明此位置已经被访问过了。

这时便可以对x3、y3进行判断了。

若p->n==x1&&p->m==y1,即比较x3、y3与终点的坐标是否相同。

若相同则找到一种走法。

此时定义inta=0;intcount[maxlen];count[a]数组的作用就是记录下每一种走法的步数;令count[a]=p->ch即可。

若不满足条件的话则把x3、y3入队;

然后i++;重复上述操作,直到i不满足条件为止,即已经走完了8种走法;

此后,进行出栈操作;判断S->front与S->rear的大小关系,若S->front>S->rear,则进行while循环,若不满足,则跳出while循环。

最后,对计数数组count[a]中的值进行比较,找出最小值,即为,从终点到起点的最小步数。

程序如下:

intmin;

min=count[0];

for(i=1;i

{

if(min>count[i])

min=count[i];

}

printf("最短步数为:

%d\n",min);

四、上机调试

1、语法错误及修正:

本程序使用了循环思想和队列的数据结构,所以程序出现的语法错误主要在于队列函数的调用及变量的定义,关键字和函数名称的书写,以及一些库函数的规范使用。

这些问题均可以根据编译器的警告提示,对应的将其解决。

2、逻辑问题的修改和调整:

循环思想的使用虽然简化了程序,但是增加了对函数循环控制的难度。

在while循环中,要实现对所有路径的查找,而不能丢掉一条,也许丢掉的便是我们所需要的,这样便造成了错误。

又因为我们对路径的查找使用了队列的数据结构,即对坐标进行了入队和出对的操作。

所以我们可以用对空的条件作为while循环的终止条件。

这样便可以无遗漏的查找起点到终点的所有路径。

还有一点容易出现逻辑错误的是在何时进行入队和出对的操作。

对入队的操作而言,在每一次行走后对于不满足条件的坐标均要进行入队操作。

而对于出对而言,每次出队操作均在对每一步的八种走法走完之后才进行,这样便可以保证路径查找没有遗漏。

3、时间,空间性能分析:

因为本算法需要用一个二维数组保存每一个位置的访问状态,也需要一个一维数组保存访问到的满足条件的步数,故其空间复杂度较高,会占据较大的内存空间,其空间复杂度为O(maxlen*maxlen)。

但是对于本算法而言,空间复杂度不但很高,时间复杂度也很大。

由于本算法将对路径的遍历转变成了对树的遍历,需要遍历所有的路径并保存,从中找出满足条件的路径。

所以无论起点和终点的位置如何,都需要进行所有的查找过程,所以对于本算法而言,时间复杂度很大,为O(8^n*n)。

由此可得,本算法的时间空间性能较差,由于知识的局限性,故本人无法对此算法进行优化。

4、经验和体会:

在刚拿到此问题时,感觉无从下手,但是经过仔细的分析,了解到,对骑士路径的查找,对八子树的树的遍历算法很相像,不过要对每次遍历的结果进行判断,从而找出满足条件的结果。

因此在具体解决问题时采用了树的数据结构思想,再经过完善和修改得出算法,并用程序语言实现。

从这个过程中我了解到对问题从认识到建立模型,之后提出方法,修改方法,最终解决问题的过程。

也使我体会到对于具体问题的解决,只要按照解决问题的过程,就不会出现盲目的情况。

五、用户使用说明

本程序运行时带有提示性语句。

开始时,程序会提示你输入骑士游历的起终点,输入格式为每一行都是一组开始位置和结束位置,位置由两个字符组成,一个是小写字母(a-h),一个是数字(0-7),起始位置结束位置由一个空格隔开。

故输入的坐标横坐标的取值范围在(a-h)之间,纵坐标的取值范围在(0-7)之间,输入起终点位置后,按回车,程序会给出从起点到终点的最短步数的值。

之后,程序会提示你是否继续输入,输入’y’表示继续输入,输入‘n’表示不再进行输入,即退出程序。

这样便可以手动的控制输入的次数。

方便查询。

六、测试结果

图五:

运行结果

 

七、附录

#include"stdio.h"

#include"stdlib.h"

#definemaxlen100

intlength=0;//记录所走的步数

staticintbx[8]={2,1,-1,-2,-2,-1,1,2};

staticintby[8]={1,2,2,1,-1,-2,-2,-1};

typedefstruct

{

intn,m;//n记录行数,m记录列数

intch;

}node;

typedefstruct//定义顺序队列类型

{

nodedata[maxlen];

intfront;

intrear;

}Sequeue;

Sequeue*setqueue()

{

Sequeue*S;

S=(Sequeue*)malloc(sizeof(Sequeue));

S->front=0;

S->rear=0;

returnS;

}

voidadd(Sequeue*S,intx,inty,intz)//入队函数

{

if(S->rearrear>=0)

{

S->rear++;

S->data[S->rear].n=x;

S->data[S->rear].m=y;

S->data[S->rear].ch=z;

}

elseprintf("error\n");

}

voiddele(Sequeue*s)//出队函数

{

if(s->frontrear)

s->front++;

else

printf("error\n");

}

voidjudge()//判断步数

{

Sequeue*S;

S=setqueue();

intx0,y0,x1,y1,x3,y3,i,j;intcount[maxlen+100];inta=0;intstep[maxlen][maxlen];

charxa,xb;

for(i=0;i

{

S->data[i].ch=0;

}

 

printf("请输入骑士游历的起终点:

\n");

scanf("%c,%d%c,%d",&xa,&y0,&xb,&y1);

x0=xa-'a';

x1=xb-'a';

for(i=0;i

for(j=0;j

{

step[i][j]=0;

}

step[x0][y0]=1;

add(S,x0,y0,0);

while(S->frontrear)

{

node*p;

x0=S->data[S->front+1].n;

y0=S->data[S->front+1].m;

for(inti=0;i<8;i++)

{

x3=bx[i]+x0;

y3=by[i]+y0;

if(x3>=0&&x3<8&&y3>=0&&y3<8&&step[x3][y3]==0)

{

p=(node*)malloc(sizeof(node));

p->ch=S->data[S->front+1].ch+1;

p->n=x3;

p->m=y3;

step[x3][y3]=1;

if(p->n==x1&&p->m==y1)

{

step[x1][y1]=0;

count[a]=p->ch;

a++;

}

else

add(S,p->n,p->m,p->ch);

}

}

dele(S);

}

intmin;

min=count[0];

for(i=1;i

if(min>count[i])

min=count[i];

printf("最短步数为:

%d\n",min);

}

 

voidmain()

{

charnn;

nn='y';

while(nn=='y')

{

judge();

printf("是否继续输入?

('y'是,'n'否)\n");

scanf("%c",&nn);

}

system("pause");

}

八、参考书目

王昆仑,李红。

数据结构与算法。

北京:

铁道工业出版社,2007年5月第一版

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

当前位置:首页 > 工程科技 > 能源化工

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

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