顺序栈基本操作实验报告.docx
《顺序栈基本操作实验报告.docx》由会员分享,可在线阅读,更多相关《顺序栈基本操作实验报告.docx(16页珍藏版)》请在冰豆网上搜索。
顺序栈基本操作实验报告
课程数据结构实验名称顺序栈基本操作第页
专业班级学号
姓名
实验日期:
年月日评分
一、实验目的
1.熟悉并能实现栈的定义和基本操作。
2.了解和掌握栈的应用。
二、实验要求
1.进行栈的基本操作时要注意栈"后进先出"的特性。
2.编写完整程序完成下面的实验内容并上机运行。
3.整理并上交实验报告。
三、实验内容
1.编写程序任意输入栈长度和栈中的元素值,构造一个顺序栈,对其进行清空、销毁、入栈、出栈以及取栈顶元素操作。
2.编写程序实现表达式求值,即验证某算术表达式的正确性,若正确,则计算该算术表达式的值。
主要功能描述如下:
(1)从键盘上输入表达式。
(2)分析该表达式是否合法:
a)是数字,则判断该数字的合法性。
若合法,则压入数据到堆栈中。
b)是规定的运算符,则根据规则进行处理。
在处理过程中,将计算该表达式的值。
c)若是其它字符,则返回错误信息。
(3)若上述处理过程中没有发现错误,则认为该表达式合法,并打印处理结果。
程序中应主要包含下面几个功能函数:
lvoidinitstack():
初始化堆栈
lintMake_str():
语法检查并计算
lintpush_operate(intoperate):
将操作码压入堆栈
lintpush_num(doublenum):
将操作数压入堆栈
lintprocede(intoperate):
处理操作码
lintchange_opnd(intoperate):
将字符型操作码转换成优先级
lintpush_opnd(intoperate):
将操作码压入堆栈
lintpop_opnd():
将操作码弹出堆栈
lintcaculate(intcur_opnd):
简单计算+,-,*,/
ldoublepop_num():
弹出操作数
四、实验步骤
(描述实验步骤及中间的结果或现象。
在实验中做了什么事情,怎么做的,发生的现象和中间结果)
第一题:
#include
usingnamespacestd;
#defineSTACK_INIT_SIZE100//存储空间初始分配量
#defineSTACKINCREMENT10//存储空间分配增量
#defineOVERFLOW-1
#defineOK1
#defineNO-1
#defineNULL0
typedefintStatus;
typedefcharSElemType;
typedefstruct
{
SElemType*base;//在栈构造之前和销毁之后,base的值为NULL
SElemType*top;//栈顶指针
intstacksize;//当前已分配的存储空间,以元素为单位
}SqStack;
StatusInitstack(SqStack&S)//构造一个空栈S
{
=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!
exit(OVERFLOW);
=;
=STACK_INIT_SIZE;
returnOK;
}//InitStack
StatusStackEmpty(SqStack&S)
{
if==
returnOK;
else
returnNO;
}
StatusClearStack(SqStack&S)//把S置为空
{
if=;
returnOK;
}
StatusDsetroyStack(SqStack&S)//销毁栈S
{
=NULL;
returnOK;
}
StatusPush(SqStack&S,SElemTypee)
//插入元素e为新的栈顶元素
{
if{
=(SElemType*)realloc,
+STACKINCREMENT)*sizeof(SElemType));
if(!
//存储分配失败
exit(OVERFLOW);
=+;
+=STACKINCREMENT;
}
*++=e;
returnOK;
}//Push
StatusPop(SqStack&S,SElemType&c)
//若栈不空,则删除S的栈顶元素,用c返回其值,并返回OK;否则返回ERROR
{
if==
returnNO;
c=*;
returnOK;
}//Pop
StatusGetTop(SqStack&S,SElemType&e)
{
if==
returnNO;
e=*;
returnOK;
}//GetTop
intmain()
{
SqStackS;
Initstack(S);
cout<<"输入要压到栈中的元素!
"<charc;
while((c=getchar())!
='\n')
{
Push(S,c);
}
GetTop(S,c);
cout<<"栈顶元素为:
"<//ClearStack(S);
//DsetroyStack(S);
for(inti=0;!
=;i++)
{
Pop(S,c);
cout<<"栈中第"<
";
cout<}
return0;
}
第二题:
#include
usingnamespacestd;
#defineSTACK_SIZE100
#defineSTACKINCREMENT10
#defineOVERFLOW-1
#defineOK1
#defineNO0
typedefintStatus;
typedefcharSElemType;
typedefstruct
{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
intmain()
{
charGetTop(SqStack&s);
StatusInitstack(SqStack&s);
Statuspush_operate(SqStack&s,SElemTypee);
Statuspush_num(SqStack&s,inte);
StatusStackempty(SqStack&s);
Statuspop_num(SqStack&s,int&c);
Statuspushoperate(SElemTypeoperate);
Statuspushnum(SElemTypenum);
Statuscaculate(SElemTypea,SElemTypeoperate,SElemTypeb);
Statuspop_operate(SqStack&s,SElemType&c);
Statuschange(SElemTypee);
charPrecede(SElemTypea,SElemTypeb);
charOperatecxz();
intm;
m=Operatecxz();
cout<return0;
}
Statuschange(SElemTypee)
{
intm;
m=e-48;
returnm;
}
StatusInitstack(SqStack&s)
{
=(SElemType*)malloc(STACK_SIZE*sizeof(SElemType));
if(!
exit(OVERFLOW);
=;
=STACK_SIZE;
returnOK;
}
StatusStackempty(SqStack&s)
{
if==
returnOK;
else
returnNO;
}
Statuspush_num(SqStack&s,inte)
{
if{
=(SElemType*)realloc,+STACKINCREMENT)*sizeof(SElemType));
if(!
exit(OVERFLOW);
=+;
+=STACKINCREMENT;
}
*++=e;
returnOK;
}
Statuspush_operate(SqStack&s,SElemTypee)
{
if{
=(SElemType*)realloc,+STACKINCREMENT)*sizeof(SElemType));
if(!
exit(OVERFLOW);
=+;
+=STACKINCREMENT;
}
*++=e;
returnOK;
}
Statuspop_operate(SqStack&s,SElemType&c)
{
if==
returnNO;
c=*;
returnOK;
}
Statuspop_num(SqStack&s,int&c)
{
if==
returnNO;
c=*;
returnOK;
}
charGetTop(SqStack&s)
{
charc;
if==
returnNO;
c=*;
returnc;
}
Statuscaculate(inta,SElemTypeoperate,intb)
{
ints;
if(operate=='+')
s=a+b;
if(operate=='-')
s=a-b;
if(operate=='*')
s=a*b;
if(operate=='/')
s=a/b;
returns;
}
StatusIn(SElemTypec)
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='#'||c=='('||c==')')
returnOK;
if(c>='0'&&c<='9')
returnNO;
return-1;
}
charPrecede(SElemTypea,SElemTypeb)
{
if(a=='+'||a=='-')
{
if(b=='+'||b=='-'||b==')'||b=='#')
return'>';
if(b=='*'||b=='/'||b=='(')
return'<';
}
if(a=='*'||a=='/')
{
if(b=='+'||b=='-'||b==')'||b=='*'||b=='/'||b=='#')
return'>';
if(b=='(')
return'<';
}
if(a=='(')
{
if(b==')')
return'=';
if(b=='+'||b=='-'||b=='*'||b=='/')
return'<';
if(b=='#')
return'';
}
if(a==')')
{
if(b==')')
return'';
if(b=='+'||b=='-'||b=='*'||b=='/'||b=='('||b=='#')
return'>';
}
if(a=='#')
{
if(b=='#')
return'=';
if(b=='+'||b=='-'||b=='*'||b=='/'||b=='(')
return'<';
if(b==')')
return'';
}
return'';
}
charOperatecxz()
{
SqStackOperate,Num;
charc,e,x;
intnum,a,b,flat=1,sz=0;
Initstack(Operate);
push_operate(Operate,'#');
Initstack(Num);
c=getchar();
while(c!
='#'||GetTop(Operate)!
='#')
{
if(In(c)==-1)
{
cout<<"inputerror!
"<flat=0;
break;
}
if(In(c)!
=1)
{
if(sz==0)
{
num=change(c);
sz=1;
c=getchar();
continue;
}
if(sz==1)
num=num*10+change(c);
c=getchar();
continue;
}
else
{
if(sz==1)
push_num(Num,num);
sz=0;
x=GetTop(Operate);
switch(Precede(GetTop(Operate),c))
{
case'<':
{
push_operate(Operate,c);
c=getchar();
break;
}
case'=':
{
pop_operate(Operate,e);
c=getchar();
break;
}
case'>':
{
pop_num(Num,a);
pop_operate(Operate,e);
pop_num(Num,b);
push_num(Num,caculate(b,e,a));
break;
}
}
}
}
pop_operate(Operate,e);
if(e!
='#')
flat=0;
if(flat==1)
{
pop_num(Num,a);
returna;
}
if(flat==0)
return0;
}
五.实验结果与讨论
(描述最终得到的结果,并进行分析说明,可能的误差原因)
第一题:
1把主函数中的ClearStack(S);DsetroyStack(S)注释掉的结果:
2不把ClearStack(S)注释掉,把栈清空:
3不把DsetroyStack(S)注释掉,即销毁栈:
出现一堆乱码,说明销毁成功。
第二题的输出:
1正常输入表达式则输出:
2如果输入的表达式出错则输出:
六.实验总结:
1在写主函数时,如果是用voidmain的形式,那么可以不用有返回值,如果是intmain或|statusmain的话,要有返回值,既末尾要有return语句。
2有时候写的没有出现问题,但运行的结果是Pressanukeytocontinue。
程序肯定有错,但为什么会出现这种问题呢。
3分号的忘记那还是很经常的,要加强注意。
4原本把ClearStack(S);DsetroyStack(S)放在for循环之后,检查不出ClearStack(S);DsetroyStack(S)的函数是否正确。
把它们for循环之前,GetTop(S,c)语句之后,再利用注释等的,就可以很明显的看出栈是否被清空或销毁。
5在做表达式的计算的时候一定要注意何时入栈何时出栈。
如果如栈与出栈的情况判断不清楚就无法得出答案。
6在定义栈的时候Num中的元素最好使用int类型的而不是char类型的。
因为这样会简化charOperatecxz()的计算复杂度。
7对于表达式的判错情况,根据题目中的提示对每次读入的字符进行判断。
8对于不是个位数的计算,首先用了个
Statuschange(SElemTypee)
{
intm;
m=e-48;
returnm;
}
把每个字符转化成int型,然后再用sz作为标记直到读入的数不是数字为止。
此时再将之前读入的数num压入Num栈中。
9对于优先级的判断按照书上给定的表格进行建立关系。
注意优先级的判断为这个实验最为关键的,也是最需要细心的地方。
只要有一个地方弄错,将导致整个实验都出错。