北理工数据结构实验二.docx
- 文档编号:3719784
- 上传时间:2022-11-24
- 格式:DOCX
- 页数:21
- 大小:93.15KB
北理工数据结构实验二.docx
《北理工数据结构实验二.docx》由会员分享,可在线阅读,更多相关《北理工数据结构实验二.docx(21页珍藏版)》请在冰豆网上搜索。
北理工数据结构实验二
《数据结构与算法设计》
实验报告
——实验二
学院:
班级:
学号:
姓名:
一、实验目的
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={
基本操作:
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)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 北理工 数据结构 实验