算法与数据结构.docx

上传人:b****6 文档编号:6746849 上传时间:2023-01-09 格式:DOCX 页数:33 大小:281.46KB
下载 相关 举报
算法与数据结构.docx_第1页
第1页 / 共33页
算法与数据结构.docx_第2页
第2页 / 共33页
算法与数据结构.docx_第3页
第3页 / 共33页
算法与数据结构.docx_第4页
第4页 / 共33页
算法与数据结构.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

算法与数据结构.docx

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

算法与数据结构.docx

算法与数据结构

数据结构与算法课程设计

 

题目:

表达式转换问题

递归替换问题

跳马问题

占用网格计算问题

目录

摘要1

一、表达式转换问题2

1.采用类语言定义相关的数据类型2

2.算法设计3

3.函数的调用关系图4

4.测试结果4

5.源程序(带注释)5

二、递归替换问题10

1.采用类语言定义相关的数据类型11

2.算法设计12

3.函数的调用关系图13

4.测试结果13

5.源程序(带注释)15

三、跳马问题15

1.采用类语言定义相关的数据类型16

2.算法设计17

3.函数的调用关系图18

4.测试结果19

5源程序20

四、占用网格计算问题25

1.采用类语言定义相关的数据类型26

2.算法设计27

3.函数的调用关系图28

4.测试结果29

5源程序30

总结-35

参考文献36

致谢37

 

摘要

第一道题目,表达式转换问题由常量、变量、运算符和括号组成。

由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行,即我们通常在书本上见到的表达式,就是中缀表达式。

但是计算机在做算术运算的时候无法识别这种表达式。

所以就有必要通过某种转化让计算机识别。

关键词:

表达式转换;长整数运算;优先级;链表;

第二道题目,程序为递归替换仿编译问题,具体要求是递归替换问题。

编写程序,扩展C/C++源文件中的#include指令(以递归的式)。

以文件名的内容替换形预编译命令“include”。

具体是用相应文件的内容来替换面的代码“预编译”的命令,即在最后的结果查看文件中没有“#include”字样,其位置为相应文件的内容,考虑到有可能在我们要替换的文件中也可能会有预编译命令,所以要用递归的算法。

通过这个代码的编写可以帮我们更深层次的理解c语言编译的过程,同时也能够练习递归的运用。

第三道题目,跳马问题是要求在64个国际象棋格子,任意位置放一个马,如何不重复地把格子走完。

能够想到的思路是用回溯,马在每一个点最多有8种跳法,遍历所有这8种可能的跳法即可得到结果。

本设计的主要工作是用C语言来实现跳马问题。

最短字符串问题是从输入中读取字符串,并按长度顺序,最短字符串优先的原则输出它们。

如果有若干字符串具有相同的长度,就按字母顺序输出它们。

最短字符串问题在C语言中是采用数组的方式建立起来的。

设计的主要工作是用C语言实现最短字符串的算法设计。

第四道题目,网格计算的由来是因为这种计算方式像格子一样的体系结构。

它试图将过剩的计算能力以及其它闲置的IT资源联系起来,以供应给那些在一定时间内需要高性能计算能力的部门。

2002年11月,日本国家高级工业科技研究所从日本向美国发送数据,速度高达707Mbps——在1万公里以上的距离之间以如此高的速度传送数据,这在世界上尚属首次,此次试验就是通过网格系统实现的。

简单地讲,网格是把互联网上的众多计算资源整合成一台虚拟的超级计算机,将以CPU为主的各种资源“拧成一股绳”,实现各种资源的全面共享。

当然,网格并不一定非要跨越国界,也可以构造地区性的网格,如城市网格、企业内部网格、局域网网格,甚至家庭网格等等——网格的根本特征,不是它的规模,而是资源共享。

关键词:

跳马最短字符串C语言表达式转换优先级网格计算整合递归替换

命令

 

一.表达式转换问题

1.数据结构设计

 

t#include

#include

#include

#include

#include

#defineMaxSize200

//两个结构体

typedefstruct

{

chardata[MaxSize];

inttop;

}OpStack;

typedefstruct

{

chardata[MaxSize];

inttop;

}SeqStack;

定义两个栈结构,用来存储中缀表达式和后缀表达式。

关系图:

 

图1、表达式转换问题的运算关系

2.算法设计

voidTranslateExpress(charstr[],charexp[])//把中缀表达式转换为后缀表达式

{

SeqStackS;

charch;

chare;

inti=0,j=0;

InitStack(&S);

ch=str[i];

i++;

while(ch!

='\0')//依次扫描中缀表达式

{

switch(ch)

{

case'(':

PushStack(&S,ch);

break;

case')':

while(GetTop(S,&e)&&e!

='(')

{

PopStack(&S,&e);

exp[j]=e;

j++;

}

PopStack(&S,&e);

break;

case'+':

case'-':

while(!

StackEmpty(S)&&GetTop(S,&e)&&e!

='(')

{

PopStack(&S,&e);

exp[j]=e;

j++;

}

PushStack(&S,ch);

break;

case'*':

case'/':

while(!

StackEmpty(S)&&GetTop(S,&e)&&e=='/'||e=='*')

{

PopStack(&S,&e);

exp[j]=e;

j++;

}

PushStack(&S,ch);

break;//是空格就忽略

case'':

break;

default:

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

{

exp[j]=ch;

j++;

ch=str[i];

i++;

}

i--;

exp[j]='';

j++;

}

ch=str[i];

i++;

}

while(!

StackEmpty(S))//将栈中剩余运算符出栈

{

PopStack(&S,&e);

exp[j]=e;

j++;

}

exp[j]='\0';

}

4.测试结果

图4:

表达式转换问题运行截图

5.源程序(带注释)

/求运算符优先级函数

intPriority(DataTypeop){

switch(op){

case'(':

case'#':

return(0);

case'-':

case'+':

return

(1);

case'*':

case'/':

return

(2);

}

}

/*转换函数将中缀表达式转换成后缀表达式*/

voidChangeExp(SeqQueue*Q){

SeqStackOS;//运算符栈

charc,t;

SeqStack*S;

S=&OS;

InitStack(S);//初始化栈

Push(S,'#');//压入栈底元素#

do{//扫描中缀表达式

c=getchar();

switch(c){

case'':

break;//去除空格符

case'1':

case'2':

case'3':

case'4':

case'5':

case'6':

case'7':

case'8':

case'9':

EnQueue(Q,c);break;

case'(':

Push(S,c);break;

case')':

case'#':

do{

t=Pop(S);

if(t!

='('&&t!

='#')

EnQueue(Q,t);

}while(t!

='('&&S->top!

=-1);break;

case'+':

case'-':

case'*':

case'/':

while(Priority(c)<=Priority(GetTop(S))){

t=Pop(S);

EnQueue(Q,t);

}

Push(S,c);break;

}//EndSwitch

}while(c!

='#');//以#号结束表达式扫描

}

二.递归替换问题

1.采用类语言定义相关的数据类型

typedefstruct//创建结构体,让文件的读写方便

{

chardata[MAX];//数据项

}char1;

int

print(charch[MAX],intn)//递归函数

{

FILE*fp,*fp1;

chars[MAX];//s,存储#后面的include

char1b[MAX];//b,文件中内容在内存中的存储位置

inti=0,k,d=0,j,flag;//switch参数,用于确认调用函数的参数

}

2.算法设计

本题主要运用了字符数组去存储数据,在通过相应的函数去读取文件中的内容,然后依次去判断是否含有#,如果有的话,下一个文件就去替换他。

3.函数的调用关系图

4.测试结果

在软件测试的过程中,刚开始对文件的读取达不到实现,后来通过翻阅资料和问同学,最后将文件的遍历以及字符串等的判断搞定

5.源代码

#include

#include

#include

#defineMAX100

typedefstruct//创建结构体,让文件的读写方便

{

chardata[MAX];//数据项

}char1;

int

print(charch[MAX],intn)//递归函数

{

FILE*fp,*fp1;

chars[MAX];//s,存储#后面的include

char1b[MAX];//b,文件中内容在内存中的存储位置

inti=0,k,d=0,j,flag;//switch参数,用于确认调用函数的参数

if((fp=fopen(ch,"rb+"))==NULL)

{

15printf("文件打开失败!

\n");

exit(0);

}

while(!

feof(fp))

{

fread(&b[i],1,sizeof(char1),fp);

i++;

if(b[i-1].data[0]=='}')//结构体数组计数器

break;

}

k=i-1;//记录b大小,可以认为是对应文件的行数

fclose(fp);

if((fp1=fopen("辅助.c","ab+"))==NULL)

{

printf("文件打开失败!

\n");exit(0);

}

d=0;//s数组存取计数器

for(i=0;i

{

if(b[i].data[0]=='#')//发现include,递归调用

print

{

for(j=2;j<9;j++)

{

s[d]=b[i].data[j];

d++;

}

if((strcmp(s,"include"))==0)

{

flag=b[i].data[19]-'0';

switch(flag)//带选择的递归调用

{

case1:

fp=print("filename1.c",1);break;

case2:

fp=print("filename2.c",2);break;

case3:

fp=print("filename3.c",3);break;

default:

break;

}

16

}

else//否则的话讲代码存入辅助文件

{

printf("%s\n",b[i].data);

fwrite(&b[i],1,sizeof(char1),fp);

fputc('\r',fp);

fputc('\n',fp);

}

}

else//否则的话讲代码存入辅助文件

{

printf("%s\n",b[i].data);

fwrite(&b[i],1,sizeof(char1),fp1);

fputc('\r',fp);

fputc('\n',fp);

}

}

lose(fp1);

return0;

}

三、跳马问题

要求在64个国际象棋格子,任意位置放一个马,如何不重复地把格子走完。

(3)

1、数据结构设计

#include

intdeltar[]={-2,-1,1,2,2,1,-1,-2};

intdeltac[]={1,2,2,1,-1,-2,-2,-1};/*马的可能走法对当前位置的横纵增量*/

 

Main()

输入r,c表示马在棋盘上的初始位置

初始化数组表示棋盘

检测是否有下一出口

(k=next(r,c))==-1)

 

此路可通过

此路不通

是否

输出满足该问题的一种正确解法,程序结束。

 

图1.流程图

图2.函数关系图

2.算法设计

A.在8*8的棋盘上的任意一个位置上放一个马(r,c),求马所在位置的出口数。

代码如下:

intexitn(intr,intc,intnexta[])

{/*求马所在位置(r,c)的出口数,nexta[]为出口号*/

inti,k,a,b;

intnum=0;

for(i=0;i<=7;i++)

{

k=(i+start)%8;

a=r+deltar[k];

b=c+deltac[k];

if(a<=7&&a>=0&&b>=0&&b<=7&&board[a][b]==0)

{

nexta[num]=k;

num++;

}

}

returnnum;

}

B.选择出口最少的那个位置。

代码如下:

intnext(intr,intc)

{/*选择下一个出口*/

intnexta[8],num,num1=0,min,i,k;/*min用来确定最少出口数*/

min=9;

num=exitn(r,c,nexta);/*num为(r,c)的出口个数*/

if(num==0)

{

return-1;/*没有出口*/

}

for(i=0;i<=num-1;i++)

{/*找出口最少的点*/

num1=number(r+deltar[nexta[i]],c+deltac[nexta[i]]);

if(num1<=min)

{

min=num1;

k=nexta[i];

}

}

returnk;/*返回出口最少的点*/

}

3.调试分析

对于跳马问题,一般情况下,可以采用回溯法找解,但对于该问题来说,只要找到一种解法即可。

然而,在写该问题的程序时,有时得到的不止一种,这就和“贪婪法”的思想相悖,在经过反复的思考和查阅资料之后,才明白须将if(step>64)放在do{}while(step<=64)循环语句之外,才能达到用“贪婪法”解决该问题的目的。

时间复杂度的计算是按照运算次数来进行的,关于空间复杂度的计算是在程序运行过程所要借助的内容空间大小。

时间复杂度:

O(n2);空间复杂度:

O(n)。

4.测试结果

图4.1初始界面

图4.2运行界面

5.源程序(带注释)

#include"stdio.h"

#defineN8

intw=0;

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

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

intch[N*N]={0};

inta[N*N+1][3]={0};

intdir[N][N][8];

intst=1;

charc='y';

intweight[N][N];

voidcaculate();

voiddirctions();

voidprint();

intcheck(inti,intj);

voidcaculate()/*计算各点的权值*/

{

inti,j,k;

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

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

for(k=0;k

{

intx,y;

x=i+way1[k];

y=j+way2[k];

if(x>=1&&x<=N&&y>=1&&y<=N)

weight[i-1][j-1]++;

}

}

intcheck(inti,intj)/*检查(i,j)是否在棋盘内*/

{

if(i<1||i>8||j<1||j>8)

return0;

return1;

}

voiddirections()/*求出各点的最佳方向序列,即优先向权值小的方向*/

{

inti,j,k,m,n1,n2,x1,y1,x2,y2,way_1,way_2;

for(i=0;i

for(j=0;j

{

for(k=0;k<8;k++)

dir[i][j][k]=k;

for(k=0;k<8;k++)

{

for(m=k+1;m<8;m++)/*对每个方向考察看有没有更好的*/

{

way_1=dir[i][j][k];

x1=i+way1[way_1];

y1=j+way2[way_1];

way_2=dir[i][j][m];

x2=i+way1[way_2];

y2=j+way2[way_2];

n1=check(x1+1,y1+1);

n2=check(x2+1,y2+1);

if(

(n1==0&&n2)||/*k方向不可达到,而m方向可达到*/

(n1&&n2&&weight[x1][y1]>weight[x2][y2])/*都可达到但m方向权值小*/

{

dir[i][j][k]=way_2;

dir[i][j][m]=way_1;/*交换两个方向值*/

}

}

}

}

}

voidprint()

{

intx,y;

printf("\n------%danswer----\n",++w);

for(x=1;x

{

printf("\n");

for(y=1;y

printf("%2d",ch[(x-1)*N+y-1]);

printf("\n");

}

printf("\nPressntoquit,pressanyotherkeytocontinue.\n");

c=getchar();/*询问是否继续输出结果*/

}

main()

{

intx,y,way,way0;

caculate();

directions();

printf("Pleaseentertherowandcolumnofthestartingpoint.\n");

scanf("%d,%d",&a[1][0],&a[1][1]);/*输入行数和列数*/

getchar();/*接收回车符*/

x=a[1][0],y=a[1][1];

ch[(x-1)*N+y-1]=1;/*在ch数组中对相应点赋值*/

while

(1)

{

if(a[1][2]>=8)/*出发点的八个方向都已走过,表示所有的方法均已找出*/

break;

if(a[st][2]>=8)/*此点的八个方向都已走过,应该退回到上一次走的点*/

{

x=a[st][0];

y=a[st][1];

ch[(x-1)*N+y-1]=0;/*将这一点被走过的痕迹抹去*/

a[st][0]=a[st][1]=a[st][2]=0;

a[st-1][2]++;/*使上一次走的点走的方向发生变化*/

st--;/*步数减一*/

}

else/*此点的八个方向未全走过,应走此方向*/

{

way0=a[st][2];

a[st][2]++;/*确定下次应走的方向*/

x=a[st][0];

y=a[st][1];

way=dir[x-1][y-1][way0];

x=a[st][0]+way1[way];

y=a[st][1]+way2[way];/*确定按这次的方向走应走到的x,y坐标*/

if(x<1||y<1||x>N||y>N||ch[(x-1)*N+y-1]!

=0)/*此点不满足要求*/

continue;

ch[(x-1)*N+y-1]=++st;/*走到这一点*/

a[st][0]=x;

a[st][1]=y;

a[st][2]=0;/*标记这一步*/

if(st==N*N)/*步数已满*/

{

print();/*输出结果*/

if(c=='n')

break;

ch[(x-1)*N+y-1]=0;

a[st][0]=a[st][1]=a[st][2]=0;

a[st-1][2]++;

st--;/*退回前一步*/

}

}

}

}

4.占用网格计算问题

考虑一个N*N的网格,其中某些方格已被占用。

如果两个方格共用公共的边,就说它们属于同一个组,如图示,一组为4个被占用的方格,3组为两个被占用的方格,2个方格被单独占用。

假设格子用二维数组来表示。

1.数据结构设计

#defineN8

intmap[N][N];

intmap2[N][N];

intstep;

intzushu=0;

intflag=0;

2.算法设计

intenter(intm)//输入

{

输入N值

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

{

flag=1;

cout<<"输入网络第"<

"<>i>>j;

if(i>=n||j>=n||i<0||j<0)//循环输入坐标

{

cout<<"!

!

!

!

ERROR

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

当前位置:首页 > 高等教育 > 教育学

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

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