数据结构笔记之十一栈的应用之表达式求值实现Word下载.docx
《数据结构笔记之十一栈的应用之表达式求值实现Word下载.docx》由会员分享,可在线阅读,更多相关《数据结构笔记之十一栈的应用之表达式求值实现Word下载.docx(12页珍藏版)》请在冰豆网上搜索。
![数据结构笔记之十一栈的应用之表达式求值实现Word下载.docx](https://file1.bdocx.com/fileroot1/2022-12/13/1059bf19-443e-41b6-b6f0-6ae18c4ed8e3/1059bf19-443e-41b6-b6f0-6ae18c4ed8e31.gif)
)
#
>
<
=
加减乘除优先性都低于“(”但是高于“)”,由运算从左到右可知,当θ1=θ2
,令θ1>
θ2
为了算法简洁,在表达式的左边和右边虚设一个“#”,这一对“#”表示一个表达式求值完成。
“(”=“)”当一对括号相遇时表示括号内已运算完成。
“)”和“(”、“#”和“(”、“(”和“#”无法相继出现如果出现则表达式出现语法错误。
为实现优先算法,可以使用两个工作栈,一个是OPTR,用于寄存运算符,一个是OPND,用于寄存运算数和运算结果。
3.算法基本思路
●首先置操作数栈为空栈,表达式起始符为“#”为栈底元素。
●依次读入表达式中的每个字符,若是操作数则进OPND栈,若是运算符则和OPTR栈的栈顶运算符比较优先权作相应操作,直至整个表达式求值完毕(OPTR栈顶元素和当前读入的字符均为“#”)。
4.求值函数EvaluateExpression实现
根据算法基本思路,代码实现如下:
intEvaluateExpression(){
intflag;
charc;
charx,theta;
chara,b;
charOP[]="
+-*/()#"
;
SqStackOPTR;
SqStackOPND;
InitStack(&
OPTR);
Push(&
OPTR,'
#'
);
OPND);
flag=getNext(&
c);
GetTop(OPTR,&
x);
while(c!
='
||x!
='
{
if(flag==0)
{
Push(&
OPND,c);
flag=getNext(&
}
else
GetTop(OPTR,&
switch(Precede(x,c))
{
case'
'
:
//栈顶元素优先级低
Push(&
OPTR,c);
flag=getNext(&
break;
//脱括号并接受下一字符
Pop(&
OPTR,&
//退栈并将运算结果入栈
OPTR,&
theta);
OPND,&
b);
a);
OPND,Operate(a,theta,b));
}
}
GetTop(OPTR,&
}
GetTop(OPND,&
freestack(&
returnc;
}
5.Main函数实现
Main函数实现
voidmain(){
intc;
printf("
Pleaseinputoneexpression:
"
c=EvaluateExpression();
Result=%d\n"
c);
结果如下图1所示:
6.源码
可以直接在VS上进行编译运行。
#include"
stdio.h"
stdlib.h"
ctype.h"
typedefintStatus;
#defineSTACK_INIT_SIZE100
#defineSTACKINCREMENT10
typedefcharSElemType;
/*放入堆栈的元素的类型*/
typedefstruct{
SElemType*base;
SElemType*top;
intstacksize;
}SqStack;
//构造一个空栈
StatusInitStack(SqStack*S){
S->
base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!
S->
base)
exit(-1);
top=S->
base;
stacksize=STACK_INIT_SIZE;
return1;
voidfreestack(SqStack*S){
free(S->
base);
//判断是否为空栈
StatusStackEmpty(SqStackS){
if(S.top==S.base)
else
return0;
//用e返回S的顶元素
StatusGetTop(SqStackS,SElemType*e){
return-1;
*e=*(S.top-1);
//插入e为新的顶元素
StatusPush(SqStack*S,SElemTypee){
if((S->
top-S->
base)>
=S->
stacksize){
base=(
SElemType*)realloc(S->
base,
(S->
stacksize+STACKINCREMENT)*sizeof(SElemType)
);
exit(-1);
top=S->
base+S->
stacksize;
stacksize+=STACKINCREMENT;
*(S->
top)=e;
top++;
//删除S的顶元素,并用e返回其值
StatusPop(SqStack*S,SElemType*e){
if(S->
top==S->
top--;
*e=*(S->
top);
//从栈底到栈顶依次对S的每个元素调用函数Visit(),一旦失败操作无效
StatusListTraverse(SqStackS,Status(*visit)(SElemType)){
SElemType*p;
p=S.base;
for(p=S.base;
p<
S.top;
p++)
(*visit)(*p);
//输出元素e
Statusoutput(SElemTypee){
%d"
e);
/*计算整数表达式的值
*表达式必须以#结束
*表达式中可以出现多位数字,
*表达式中可以出现空格
*运算符包括+,-,*,/,(,)
*运算结果可以是多位整数,并以整数的形式返回
*/
/*判断输入的某个字符是否是运算符
*c表示输入的字符
*op数组中存放系统能识别的运算符
Statusin(charc,charop[]){
char*p;
p=op;
while(*p!
\0'
){
if(c==*p)
p++;
/*比较两个运算符的优先级
*a,b中存放待比较的运算符
*'
表示a>
b
0'
表示不可能出现的比较
charPrecede(chara,charb){
inti,j;
charpre[][7]={
/*运算符之间的优先级制作成一张表格*/
{'
'
},
}};
switch(a){
case'
+'
i=0;
break;
-'
i=1;
*'
i=2;
/'
i=3;
('
i=4;
)'
i=5;
i=6;
switch(b){
j=0;
j=1;
j=2;
j=3;
j=4;
j=5;
j=6;
returnpre[i][j];
/*进行实际的运算
*a,b中分别以整数的形式存放两个待运算的操作数
*theta中存放代表操作符的字符
*结果以整数的形式返回
intOperate(inta,chartheta,intb){
inti,j,result;
i=a;
j=b;
switch(theta){
result=i+j;
result=i-j;
result=i*j;
result=i/j;
returnresult;
/*从输入缓冲区中获得下一个整数或运算符,并通过n带回到主调函数
*返回值为1表示获得的是运算符
*返回值为0表示获得的是整形操作数
intgetNext(char*n){
*n=0;
while((c=getchar())=='
'
/*跳过一个或多个空格*/
isdigit(c)){/*通过函数判断如果字符不是数字,那么只能是运算符*/
*n=c;
do{/*能执行到该条语句,说明字符是数字,此处用循环获得连续的数字*/
*n=*n*10+(c-'
/*把连续的数字字符转换成相对应的整数*/
c=getchar();
}while(isdigit(c));
/*如果下一个字符是数字,进入下一轮循环*/
ungetc(c,stdin);
/*新读入的字符不是数字,可能是运算符,为了不影响下次读入,把该字符放回到输入缓冲区*/
//退栈并将运算结果入栈