北理工数据结构实验二.docx

上传人:b****5 文档编号:3719784 上传时间:2022-11-24 格式:DOCX 页数:21 大小:93.15KB
下载 相关 举报
北理工数据结构实验二.docx_第1页
第1页 / 共21页
北理工数据结构实验二.docx_第2页
第2页 / 共21页
北理工数据结构实验二.docx_第3页
第3页 / 共21页
北理工数据结构实验二.docx_第4页
第4页 / 共21页
北理工数据结构实验二.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

北理工数据结构实验二.docx

《北理工数据结构实验二.docx》由会员分享,可在线阅读,更多相关《北理工数据结构实验二.docx(21页珍藏版)》请在冰豆网上搜索。

北理工数据结构实验二.docx

北理工数据结构实验二

 

《数据结构与算法设计》

实验报告

——实验二

 

学院:

班级:

学号:

姓名:

 

一、实验目的

1.通过实验实践、巩固栈的相关操作;

2.熟悉VC环境,加强编程、调试的练习;

3.用C语言实现栈的抽象数据类型,实现栈的建立、进栈、出栈、取数据等基本操作;

4.用C语言实现判断运算符优先级、表达式求值等基本操作;

5.理论知识与实际问题相结合,利用上述基本操作实现简单计算器。

二、实验内容

1、简单计算器。

请按照四则运算加、减、乘、除、幂(^)和括号的优先关系和惯例,编写计算器程序。

要求:

1从键盘输入一个完整的表达式,以回车作为表达式输入结束的标志。

2输入表达式中的数值均为大于等于零的整数。

中间的计算过程如果出现小数也只取整。

例如,输入:

4+2*5=输出:

14

输入:

(4+2)*(2-10)=输出:

-48

三、程序设计

1、概要设计

为实现上述程序功能,应用栈存储运算符和操作数,为此需要建立一个抽象数据类型:

栈。

(1)、栈的抽象数据类型定义为:

ADTStack{

数据对象:

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

数据关系:

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

基本操作:

InitStack(&S)

操作结果:

创建一个空栈S。

Push(&S,e)

初始条件:

栈S已存在

操作结果:

插入运算符e作为新的栈顶元素

GetTop(&S)

初始条件:

栈S已存在且非空

操作结果:

用e返回寄存运算符栈S的栈顶元素

Pop(&S,&e)

初始条件:

栈S已存在且非空

操作结果:

删除寄存运算符栈S的栈顶元素

Operate(a,theta,b)

初始条件:

a,b为整数,theta为运算符

操作结果:

返回a与b运算的结果

Precede(d,c)

初始条件:

d,c为运算符

操作结果:

若d优先级大于c,返回‘>’;若d优先级小于c,返回‘<’;若d优先级等于c,返回‘=’;

EvaluateExpression()

初始条件:

输入合法的表达式

操作结果:

返回表达式的值

}ADTStack

⑵主程序流程

调用EvaluateExpression()函数计算表达式的值,并将结果输出在屏幕上。

⑶各函数模块的调用关系

先由主函数调用计算求值函数;

再由求值模块调用栈构造函数,构造两个栈分别用来保存操作数和运算符,然后根据情况多次调用进栈、出栈、取栈顶元素、判断运算符优先级、计算表达式的值等多个函数,计算并返回表达式的值;

最后由主函数在屏幕上输出表达式的结果。

⑷流程图

2、详细设计

(1)、宏定义

#defineSTACK_INIT_SIZE10//栈存储空间的初始分配量

#defineSTACKINCREMENT10//空间的分配增量

#defineOK1//正确时返回值为真

#defineERROR0//出错时返回值为假

(2)、抽象数据类型定义

typedefcharElemType1;//定义元素类型1为char

typedefintElemType2;//定义元素类型2为int

typedefstruct

{//栈SqStack1存储元素为char

ElemType1*base;//栈空间基址

ElemType1*top;//栈顶指针

intstacksize;//当前分配的栈空间大小

}SqStack1;

typedefstruct

{//栈SqStack2存储元素为int

ElemType2*base;//栈空间基址

ElemType2*top;//栈顶指针

intstacksize;//当前分配的栈空间大小

}SqStack2;

(3)、操作算法程序实现:

intInitStack1(SqStack1&S)

{//构造一个空栈S

S.base=(ElemType1*)malloc(STACK_INIT_SIZE*sizeof(ElemType1));

//为顺序栈动态分配存储空间

if(!

S.base)exit(OVERFLOW);//分配失败

S.top=S.base;

S.stacksize=STACK_INIT_SIZE;

returnOK;

}//InitStack1

intPush1(SqStack1&S,ElemType1e)

{//将元素e插入栈中,使其成为新的栈顶元素

if(S.top-S.base>=S.stacksize)//若栈满则追加存储空间

{S.base=(ElemType1*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType1));

if(!

S.base)exit(OVERFLOW);//存储分配失败

S.top=S.base+S.stacksize;

S.stacksize+=STACKINCREMENT;

}

*S.top++=e;//元素e插入栈顶,后修改栈顶指针

returnOK;//*S.top=e;S.top++;

}//Push1

charGetTop1(SqStack1S)

{//取栈顶元素并返回其值

ElemType1e;

if(S.top==S.base)

returnERROR;//栈空

e=*(S.top-1);

returne;

}//GetTop1

intPop1(SqStack1&S,ElemType1&e)

{//删除栈顶元素,并用e返回其值

if(S.top==S.base)

returnERROR;//栈空

e=*--S.top;//--S.top;e=*S.top;

returnOK;

}//Pop1

intInitStack2(SqStack2&S)

{//构造一个空栈S

S.base=(ElemType2*)malloc(STACK_INIT_SIZE*sizeof(ElemType2));

//为顺序栈动态分配存储空间

if(!

S.base)exit(OVERFLOW);//分配失败

S.top=S.base;

S.stacksize=STACK_INIT_SIZE;

returnOK;

}//InitStack2

intPush2(SqStack2&S,ElemType2e)

{//将元素e插入栈中,使其成为新的栈顶元素

if(S.top-S.base>=S.stacksize)//若栈满则追加存储空间

{S.base=(ElemType2*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType2));

if(!

S.base)exit(OVERFLOW);//存储分配失败

S.top=S.base+S.stacksize;

S.stacksize+=STACKINCREMENT;

}

*S.top++=e;//元素e插入栈顶,后修改栈顶指针

returnOK;//*S.top=e;S.top++;

}//Push2

intGetTop2(SqStack2S)

{//取栈顶元素并返回其值

ElemType2e;

if(S.top==S.base)

returnERROR;//栈空

e=*(S.top-1);

returne;

}//GetTop2

intPop2(SqStack2&S,ElemType2&e)

{//删除栈顶元素,并用e返回其值

if(S.top==S.base)

returnERROR;//栈空

e=*--S.top;//--S.top;e=*S.top;

returnOK;

}//Pop2

intIn(charc)

{//判断c是否为运算符,是则返回1,否则返回0。

if(c=='+'||c=='-'||c=='*'||c=='/'||c=='^'||c=='('||c==')'||c=='=')

return1;

else

return0;

}//In

charPrecede(chard,charc)

{//判断运算符d与运算符c的优先级

switch(c)

{

case'+':

switch(d)

{

case'+':

return'>';break;

case'-':

return'>';break;

case'*':

return'>';break;

case'/':

return'>';break;

case'^':

return'>';break;

case'(':

return'<';break;

case')':

return'>';break;

case'=':

return'<';break;

}

case'-':

switch(d)

{

case'+':

return'>';break;

case'-':

return'>';break;

case'*':

return'>';break;

case'/':

return'>';break;

case'^':

return'>';break;

case'(':

return'<';break;

case')':

return'>';break;

case'=':

return'<';break;

}

case'*':

switch(d)

{

case'+':

return'<';break;

case'-':

return'<';break;

case'*':

return'>';break;

case'/':

return'>';break;

case'^':

return'>';break;

case'(':

return'<';break;

case')':

return'>';break;

case'=':

return'<';break;

}

case'/':

switch(d)

{

case'+':

return'<';break;

case'-':

return'<';break;

case'*':

return'>';break;

case'/':

return'>';break;

case'^':

return'>';break;

case'(':

return'<';break;

case')':

return'>';break;

case'=':

return'<';break;

}

case'^':

switch(d)

{

case'+':

return'<';break;

case'-':

return'<';break;

case'*':

return'<';break;

case'/':

return'<';break;

case'^':

return'>';break;

case'(':

return'<';break;

case')':

return'>';break;

case'=':

return'<';break;

}

case'(':

switch(d)

{

case'+':

return'<';break;

case'-':

return'<';break;

case'*':

return'<';break;

case'/':

return'<';break;

case'^':

return'<';break;

case'(':

return'<';break;

case'=':

return'<';break;

}

case')':

switch(d)

{

case'+':

return'>';break;

case'-':

return'>';break;

case'*':

return'>';break;

case'/':

return'>';break;

case'^':

return'>';break;

case'(':

return'=';break;

case')':

return'>';break;

}

case'=':

switch(d)

{

case'+':

return'>';break;

case'-':

return'>';break;

case'*':

return'>';break;

case'/':

return'>';break;

case'^':

return'>';break;

case')':

return'>';break;

case'=':

return'=';break;

}

}

}//Precede

intOperate(inta,chartheta,intb)

{//运算函数

switch(theta)

{

case'+':

return(a+b);

case'-':

return(a-b);

case'*':

return(a*b);

case'/':

return(a/b);

case'^':

return(pow(a,b));

}

}//Operate

intEvaluateExpression()

{//算术表达式求值的算符优先算法。

设OPTR和OPND分别为运算符栈和操作数栈,OP为运算符、界限符集合。

charc,theta;

intnum,a,b;

SqStack1OPTR;

SqStack2OPND;

InitStack1(OPTR);

InitStack2(OPND);

Push1(OPTR,'=');

c=getchar();

while(c!

='='||GetTop1(OPTR)!

='=')

{

num=0;

if(!

In(c))//In(c)判断c是否为运算符

{

while(!

In(c))

{

num*=10;

num+=(c-48);

c=getchar();

}

Push2(OPND,num);

}//不是运算符则进栈

else

{

switch(Precede(GetTop1(OPTR),c))

{//判定OPTR的栈顶运算符1与读入的运算符2间的优先关系

case'<':

//新输入的算符c优先级高,c进栈

Push1(OPTR,c);c=getchar();break;

case'=':

//脱括号并接收下一字符

Pop1(OPTR,c);c=getchar();break;

case'>':

//新输入的算符c优先级低,即栈顶算符优先权高

//出栈并将运算结果入栈OPND

Pop1(OPTR,theta);

Pop2(OPND,b);

Pop2(OPND,a);

Push2(OPND,Operate(a,theta,b));//进行二元运算athetab

break;

}//switch

}

}//while

returnGetTop2(OPND);

}//EvaluateExpression

(4)、主程序的代码实现:

intmain()

{

intx;//定义整形变量x用以接受表达式的值

x=EvaluateExpression();//返回表达式的值

printf("%d\n",x);//输出表达式的值

return0;

}

四、程序调试分析

1.引用标识符&不符合C语言语法,应使用C++;

2.存操作数和运算符的栈元素类型不一样,所以要定义两种元素类型、两种栈以及分别对应的基本操作;

3.操作数进栈时要注意连续读完所有非运算符的字符并且把字符型转换为整型;

4.pow()函数返回值为double,直接取整会丢失数据,组建时会有警告提示。

五、用户使用说明

1.本程序的运行环境为DOS操作系统,执行文件为:

实验二.exe,双击打开文件。

2.进入程序后,输入要计算的表达式,按Enter键结束。

3.屏幕输出上述表达式的结果,按任意键退出程序。

六、程序运行结果

测试一:

测试二:

测试三:

七、程序清单

#include

#include

#include

typedefcharElemType1;//定义元素类型1为char

typedefintElemType2;//定义元素类型2为int

#defineSTACK_INIT_SIZE10//栈存储空间的初始分配量

#defineSTACKINCREMENT10//空间的分配增量

#defineOK1//正确时返回值为真

#defineERROR0//出错时返回值为假

typedefstruct

{//栈SqStack1存储元素为char

ElemType1*base;//栈空间基址

ElemType1*top;//栈顶指针

intstacksize;//当前分配的栈空间大小

}SqStack1;

typedefstruct

{//栈SqStack2存储元素为int

ElemType2*base;//栈空间基址

ElemType2*top;//栈顶指针

intstacksize;//当前分配的栈空间大小

}SqStack2;

intInitStack1(SqStack1&S)

{//构造一个空栈S

S.base=(ElemType1*)malloc(STACK_INIT_SIZE*sizeof(ElemType1));

//为顺序栈动态分配存储空间

if(!

S.base)exit(OVERFLOW);//分配失败

S.top=S.base;

S.stacksize=STACK_INIT_SIZE;

returnOK;

}//InitStack1

intPush1(SqStack1&S,ElemType1e)

{//将元素e插入栈中,使其成为新的栈顶元素

if(S.top-S.base>=S.stacksize)//若栈满则追加存储空间

{S.base=(ElemType1*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType1));

if(!

S.base)exit(OVERFLOW);//存储分配失败

S.top=S.base+S.stacksize;

S.stacksize+=STACKINCREMENT;

}

*S.top++=e;//元素e插入栈顶,后修改栈顶指针

returnOK;//*S.top=e;S.top++;

}//Push1

charGetTop1(SqStack1S)

{//取栈顶元素并返回其值

ElemType1e;

if(S.top==S.base)

returnERROR;//栈空

e=*(S.top-1);

returne;

}//GetTop1

intPop1(SqStack1&S,ElemType1&e)

{//删除栈顶元素,并用e返回其值

if(S.top==S.base)

returnERROR;//栈空

e=*--S.top;//--S.top;e=*S.top;

returnOK;

}//Pop1

intInitStack2(SqStack2&S)

{//构造一个空栈S

S.base=(ElemType2*)malloc(STACK_INIT_SIZE*sizeof(ElemType2));

//为顺序栈动态分配存储空间

if(!

S.base)exit(OVERFLOW);//分配失败

S.top=S.base;

S.stacksize=STACK_INIT_SIZE;

returnOK;

}//InitStack2

intPush2(SqStack2&S,ElemType2e)

{//将元素e插入栈中,使其成为新的栈顶元素

if(S.top-S.base>=S.stacksize)//若栈满则追加存储空间

{S.base=(ElemType2*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(ElemType2));

if(!

S.base)exit(OVERFLOW);//存储分配失败

S.top=S.base+S.stacksize;

S.stacksize+=STACKINCREMENT;

}

*S.top++=e;//元素e插入栈顶,后修改栈顶指针

returnOK;//*S.top=e;S.top++;

}//Push2

intGetTop2(SqStack2S)

{//取栈顶元素并返回其值

ElemType2e;

if(S.top==S.base)

returnERROR;//栈空

e=*(S.top-1)

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

当前位置:首页 > 小学教育 > 语文

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

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