数据结构课程设计1.docx

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

数据结构课程设计1.docx

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

数据结构课程设计1.docx

数据结构课程设计1

 

软件学院

课程设计报告书

 

课程名称数据结构

设计题目算术表达式求值演示

专业班级软件工程09-05

学号0920010504

姓名韩亮

指导教师孙宁

 

2010年12月31日

目录

1.设计时间……………………………………………………………3

2.设计目的……………………………………………………………3

3.设计任务……………………………………………………………3

4.设计内容……………………………………………………………3

4.1需求分析……………………………………………………………3.

4.1.1程序所要实现的功能……………………………………………3

4.1.2输入形式和输入值的范围………………………………………3

4.1.3输出形式…………………………………………………………3

4.1.4测试数据…………………………………………………………3

4.2总体设计……………………………………………………………3

4.2.1设定栈的抽象数据类型定义:

…………………………………3

4.2.2程序流程图:

……………………………………………………4

4.2.3模块调用关系:

…………………………………………………5

4.3详细设计:

………………………………………………………5

4.3.1数据类型的实现…………………………………………………5

4.3.2主程序和其他主要函数的伪码:

…………………………………6

4.3.3各函数之间的调用关系:

………………………………………10

4.4测试与分析…………………………………………………………11

4.4.1测试……………………………………………………………11

4.4.2问题解决与讨论分析…………………………………………12

4.4.3时间和空间复杂度分析和改进设想…………………………12

4.5附录(原代码及必要注释)………………………………………12

5.总结与展望…………………………………………………………18

参考文献………………………………………………………………19

成绩评定………………………………………………………………19

 

1.设计时间

2010.12.27—2010.12.31

2.设计目的

通过设计掌握数据结构课程中学到的基本理论和算法并综合运用于解决实践问题中,它是理论与实践的结合。

通过做这个算术表达式求值演示的实验,来使我们对栈有一个更深层次的了解。

3.设计任务

算术表达式求值演示。

设计一个程序,用栈来求解表达式的值,要求以表达式的形式输入,以#号结束,运算符为+-*/(),要有输出结果。

所能达到的功能,做+-*/运算。

4.设计内容

4.1需求分析

4.1.1程序所要实现的功能

实现用栈的入栈出栈演示表达式求值过程。

4.1.2输入形式和输入值的范围

以表达式的形式输入,输入值在0-9之间。

操作符的范围——+-*/()

4.1.3输出形式

输出的形式以#号结束。

4.1.4测试数据:

正确测试:

能以正确的形式输出。

错误测试:

不能输出正确的结果,只能输出个错误的表达式。

4.2总体设计

4.2.1设定栈的抽象数据类型定义:

ADTStack{

数据对象:

D={ai|ai∈ElemSet,i=1,2,...,n,n≥0}

数据关系:

R1={|ai-1,ai∈D,i=2,...,n}

约定an端为栈顶,a1端为栈底。

基本操作:

InitStack(&S)

操作结果:

构造一个空栈S。

GetTop(S,&e)

初始条件:

栈S已存在且非空。

操作结果:

用e返回S的栈顶元素。

Push(&S,e)

初始条件:

栈S已存在。

操作结果:

插入元素e为新的栈顶元素。

StackEmpty(S)

初始条件:

栈S已存在。

操作结果:

若栈S为空栈,则返回TRUE,否则FALE。

Pop(&S,&e)

初始条件:

栈S已存在且非空。

操作结果:

删除S的栈顶元素,并用e返回其值。

}ADTStack

4.2.2主程序流程:

InitStack(Stack*s)和InitStack2(Stack2*s)分别构造运算符栈与构造操作数栈,Push(Stack*s,charch)运算符栈插入ch为新的栈顶元素,Push2(Stack2*s,intch)操作数栈插入ch为新的栈顶元素,Pop(Stack*s)删除运算符栈s的栈顶元素,用p返回其值,Pop2(Stack2*s)删除操作数栈s的栈顶元素,用p返回其值,GetTop(Stacks)用p返回运算符栈s的栈顶元素,GetTop2(Stack2s)用p返回操作数栈s的栈顶元素。

(1)In(charch)判断字符是否是运算符功能,运算符即返回1,该功能

(2)Precede(charc1,charc2)判断运算符优先权功能,该函数判断运算符c1,c2的优先权。

(3)Operate(inta,charop,intb)操作数用对应的运算符进行运算功能。

运算结果直接返回。

(4)num(intn)求操作数的长度功能,需要用itoa函数把int型转换成字符串型,strlen函数可求字符长度。

(5)EvalExpr()主要操作函数运算功能。

(1)、主程序模块

voidmain()

{

structSqstackopnd;//操作数栈

structSqstackoptr;//操作符栈

elemtyperesult;

result=evaluate(opnd,optr);

printf("theresultis%d\n",result);

}

(2)运算模块——实现数据表达式的运算

(3)栈模块——实现栈抽象数据类型

4.2.3模块调用关系:

主模块先调用expr函数,之后依次调InitStack(&OPTR);Push(&OPTR,'#');InitStack2(&OPND);最后调用运算模块EvalExpr()。

4.3详细设计:

4.3.1数据类型的实现

因为表达式是由操作符,运算符和界限符组成的。

如果只用一个char类型栈,不能满足2位以上的整数,所以还需要定义一个int类型的栈用来寄存操作数。

/*定义字符类型栈*/

typedefstruct{

intstacksize;

char*base;

char*top;

}Stack;

/*定义整型栈*/

typedefstruct{

intstacksize;

int*base;

int*top;

}Stack2;

4.3.2主程序和其他主要函数的伪码:

1、Precede(charc1,charc2)判断运算符优先权,返回优先权高的。

算符间的优先关系如下:

+

-

*

/

#

+

>

<

<

<

<

>

>

-

>

>

<

<

<

>

>

*

>

>

>

>

<

>

>

/

>

>

>

>

<

>

>

<

<

<

<

<

=

>

>

>

>

>

>

#

<

<

<

<

<

=

表1

算法伪代码如下:

charPrecede(charc1,charc2)

{

staticchararray[49]={

'>','>','<','<','<','>','>',

'>','>','<','<','<','>','>',

'>','>','>','>','<','>','>',

'>','>','>','>','<','>','>',

'<','<','<','<','<','=','!

',

'>','>','>','>','!

','>','>',

'<','<','<','<','<','!

','='};//用一维数组存储49种情况

switch(c1)

{

/*i为下面array的横标*/

case'+':

i=0;break;

case'-':

i=1;break;

case'*':

i=2;break;

case'/':

i=3;break;

case'(':

i=4;break;

case')':

i=5;break;

case'#':

i=6;break;

}

switch(c2)

{

/*j为下面array的纵标*/

case'+':

j=0;break;

case'-':

j=1;break;

case'*':

j=2;break;

case'/':

j=3;break;

case'(':

j=4;break;

case')':

j=5;break;

case'#':

j=6;break;

}

return(array[7*i+j]);/*返回运算符array[7*i+j]为对应的c1,c2优先关系*/

}

2.intEvalExpr()主要操作函数。

算法概要流程图:

利用该算法对算术表达式3*(7-2)求值操作过程如下:

步骤

OPTR栈

OPND栈

输入字符

主要操作

1

#

3*(7-2)#

Push(OPND,’3’)

2

#

3

*(7-2)#

Push(OPTR,’*’)

3

#*

3

(7-2)#

Push(OPNR,’(’)

4

#*(

3

7-2)#

Push(OPND,’7’)

5

#*(

37

-2)#

Push(OPNR,’-’)

6

#*(-

37

2)#

Push(OPND,’2’)

7

#*(-

372

)#

Operate(‘7’,’-’,’2’)

8

#*(

35

)#

Pop(OPTR)

9

#*

35

#

Operate(‘3’,’*’,5’)

10

#

15

#

Return(GetTop2(OPND))

表2

intEvalExpr(void)

{

charc,theta,x,m,ch;

inta,b;

c=*ptr++;

while(c!

='#'||GetTop(OPTR)!

='#')

if(!

In(c))

{

m=atoi(&c);

Push(&OPND,m);

c=*ptr++;

}

else

switch(Precede(GetTop(OPTR),c))

{

case'<':

Push(&OPTR,c);

c=*ptr++;

break;

case'=':

x=Pop(&OPTR);

c=*ptr++;

break;

case'>':

theta=Pop(&OPTR);

b=Pop(&OPND);a=Pop(&OPND);

Push(&OPND,Operate(a,theta,b));

break;

}

returnGetTop(OPND);

}

主函数:

intmain(void)

{

char*pc;

printf("请输入要求的表达式并以"#"结尾:

");

gets(expr);

pc=expr;

if(expr[0]=='\0')

{

printf("请输入一个有效的表达式以#号结束\n");

printf("请再次输入要求表达式并以“#”结尾:

");

gets(expr);

}

else

{

while(*pc!

='\0')

pc++;

pc--;

if(*pc!

='#')

{

printf("请输入要求的表达式并以"#"结尾:

\n");

printf("请再次输入要求表达式并以“#”结尾:

");

gets(expr);

}

}

4.3.3各函数之间的调用关系:

①输入表达式调用expr;

②表达式的值调用EvalExpr()

算术式运算EvalExpr()用到GetTop,Push,Precede以及Pop函数

4.4测试与分析

4.4.1测试

正确测试:

2*(7-4)#

请输入一个表达式以#号结束:

2*(7-4)#

12PUSH(OPTR,#)

2#*PUSH(OPND,2)

3#2(PUSH(OPTR,*)

4#*27PUSH(OPTR,()

5#*(2-PUSH(OPND,7)

6#*(274PUSH(OPTR,-)

7#*(-27)PUSH(OPND,4)

8#*(-274#POP(OPTR)

9#*(274#POP(OPND)

10#*(27#POP(OPND)

11#*(2#OPERATE(7,-,4)

12#*(2#PUSH(OPND,3)

13#*(23#POP(OPTR)

14#*23

输出结果为:

6

错误测试:

12*6#

请输入一个表达式以#号结束:

12*6#

11PUSH(OPTR,#)

2#2PUSH(OPND,1)

3#1*PUSH(OPND,2)

4#126PUSH(OPTR,*)

5#*12#PUSH(OPND,6)

6#*126

输出结果为:

12

4.4.2问题解决与讨论分析

1、本设计的关键是运算符优先级的判断,由于优先级的错判,很容导致果的运算错误。

要明晰判断当前运算符和运算符栈栈顶元素的先后顺序,这个易出错误。

2、在本次设计中充分利用了,栈先进后出的特点。

3、二位数输入计算。

我们应将二位数转换成一位数,将两个数字做特殊处理,放入同一个栈的同一位置,出栈时同时出栈,并加以计算。

4.4.3时间和空间复杂度分析和改进设想

空间复杂度和时间复杂度由于算术式计算量较小,因此不会占用过多时间复杂度,空间复杂度则决定于操作数与操作符的多少。

改进设想:

运用将一个式子分为多个部分,逐次计算。

4.5附录(原代码及必要注释)

#include

#include

#include

#include

#defineDEBUG

#defineNULL0

#defineERROR-1

#defineSTACKSIZE20

/*定义字符类型栈*/

typedefstruct{

charstackname[20];

char*base;

char*top;

}Stack;

/*-----------------全局变量---------------*/

StackOPTR,OPND;/*定义前个运算符栈,后个操作数栈*/

charexpr[255]="";/*存放表达式串*/

char*ptr=expr;

intstep=0;/*计算的步次*/

intInitStack(Stack*s,char*name)

{

s->base=(char*)malloc(STACKSIZE*sizeof(char));

if(!

s->base)exit(ERROR);

strcpy(s->stackname,name);

s->top=s->base;

return1;

}

intIn(charch)

{

return(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='('||ch==')'||ch=='#');

}

voidOutputStatus(void)

{

char*s;

/*step*/

printf("\n%-8d",++step);

/*OPTR*/

for(s=OPTR.base;s

printf("%c",*s);

printf("\t");

/*OPND*/

for(s=OPND.base;s

printf("%d",*s);

/*inputchar*/

printf("\t\t%c",*ptr);

}

intPush(Stack*s,charch)

{

#ifdefDEBUG

char*name=s->stackname;

OutputStatus();

if(strcmp(name,"OPND")==0)

printf("\tPUSH(%s,%d)",name,ch);

else

printf("\tPUSH(%s,%c)",name,ch);

#endif

*s->top=ch;

s->top++;

return0;

}

charPop(Stack*s)

{

charp;

#ifdefDEBUG

OutputStatus();

printf("\tPOP(%s)",s->stackname);

#endif

s->top--;

p=*s->top;

return(p);

}

charGetTop(Stacks)

{

charp=*(s.top-1);

return(p);

}

/*判断运算符优先权,返回优行权高的*/

charPrecede(charc1,charc2)

{

inti=0,j=0;

staticchararray[49]={'>','>','<','<','<','>','>',

'>','>','<','<','<','>','>',

'>','>','>','>','<','>','>',

'>','>','>','>','<','>','>',

'<','<','<','<','<','=','!

',

'>','>','>','>','!

','>','>',

'<','<','<','<','<','!

','='};

switch(c1)

{

/*i为下面array的横标*/

case'+':

i=0;break;

case'-':

i=1;break;

case'*':

i=2;break;

case'/':

i=3;break;

case'(':

i=4;break;

case')':

i=5;break;

case'#':

i=6;break;

}

switch(c2)

{

/*j为下面array的纵标*/

case'+':

j=0;break;

case'-':

j=1;break;

case'*':

j=2;break;

case'/':

j=3;break;

case'(':

j=4;break;

case')':

j=5;break;

case'#':

j=6;break;

}

return(array[7*i+j]);/*返回运算符*/

}

/*操作函数*/

intOperate(inta,charop,intb)

{

#ifdefDEBUG

OutputStatus();

printf("\tOPERATE(%d,%c,%d)",a,op,b);

#endif

switch(op)

{

case'+':

return(a+b);

case'-':

return(a-b);

case'*':

return(a*b);

case'/':

return(a/b);

}

return0;

}

intEvalExpr(void)

{

charc,theta,x,m,ch;

inta,b;

c=*ptr++;

while(c!

='#'||GetTop(OPTR)!

='#')

if(!

In(c))

{

m=atoi(&c);

Push(&OPND,m);

c=*ptr++;

}

else

switch(Precede(GetTop(OPTR),c))

{

case'<':

Push(&OPTR,c);

c=*ptr++;

break;

case'=':

x=Pop(&OPTR);

c=*ptr++;

break;

case'>':

theta=Pop(&OPTR);

b=Pop(&OPND);a=Pop(&OPND);

Push(&OPND,Operate(a,theta,b));

break;

}

returnGetTop(OPND);

}

intmain(void)

{

char*pc;

printf("Inputtheexpression(endwith\"#\"sign):

");

gets(expr);

pc=expr;

if(expr[0]=='\0')

{

printf("Pleaseinputavalidexpression!

\n");

printf("Inputtheexpressionagain(endwith\"#\"sign):

");

gets(expr);

}

else

{

while(*pc!

='\0')

pc++;

pc--;

if(*pc!

='#')

{

printf("Pleaseasuretheexpressionendwith\"#\"sign!

\n");

printf("Inputtheexpressionagain(endwith\"#\"sign):

");

gets(expr);

}

}

5.总结与展望

这次课程设计让我有一个深刻的体会,那就是细节决定成败,编程最需要的是严谨,如何的严谨都不过分,往往检查了半天发现错误发生在某个括号,分号,引号,或者数据类型上。

就像我在写EvalExpr()函数时,忘了指针的地址符值不用加*号,这一点小小

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

当前位置:首页 > 医药卫生 > 基础医学

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

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