您的位置:首页 > 其它

课程设计 栈之 后缀表达式求值 中缀表达式转后缀表达式

2017-12-15 14:49 106 查看
题目描述

为了便于处理表达式,常常将普通表达式(称为中缀表示)转换为后缀{运算符在后,如X/Y写为XY/表达式。在这样的表示中可以不用括号即可确定求值的顺序,如:(P+Q)*(R-S) → PQ+RS-*。后缀表达式的处理过程如下:扫描后缀表达式,凡遇操作数则将之压进堆栈,遇运算符则从堆栈中弹出两个操作数进行该运算,将运算结果压栈,然后继续扫描,直到后缀表达式被扫描完毕为止,此时栈底元素即为该后缀表达式的值。输入

输入一行表示后缀表达式,数与数之间一定有空格隔开(可能不只一个空格),最后输入@表示输入结束。

数据保证每一步的计算结果均为不超过100000的整数。

输出

输出一个整数,表示该表达式的值.

样例输入
14  3 20 5 / *8 - + @

样例输出

18

题目已经告知可以使用栈。(1.自己模拟出栈这种数据结构 2.使用C++ STL的内容 )本题相对简单,只是在输入一行后缀表达式的时候要进行预处理,将字符型的运算符号和运算数字整理好即可

include <cstdio>
#include <malloc.h>
#include <cstring>
using namespace std;
#define STACK_INIT_SIZE 10
#define STACK_INCREMENT 2
#define OVERFLOW 0
#define TRUE 1
#define FALSE 0
#define ERROR 0
#define OK 1
char opera[100005];
typedef int Status;
typedef int SElemType;
struct SqStack
{
SElemType *base; //在栈构造之前和销毁之后,base=NULL
SElemType *top; //栈顶指针
int stacksize; //当前分配的存贮空间
};
//S.top=存储的地址,*S.top=存储的内容
void InitStack(SqStack &S);
int StackLength(SqStack S);
Status GetTop(SqStack S,SElemType &e);//若栈不空,用e返回栈顶元素,并返回OK
void Push(SqStack &S,SElemType e); //插入元素e为栈顶新元素,
Status Pop(SqStack &S,SElemType &e); //若栈S不空,则删除S的栈顶元素,用e返回其值,并且返回OK

void InitStack(SqStack &S)
{
S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!S.base)
exit(OVERFLOW);//动态分配存贮空间失败,退出
S.top=S.base; //栈顶指向栈底(空栈)
S.stacksize=STACK_INIT_SIZE; //存储空间为初始分配量
}

Status GetTop(SqStack S,SElemType &e)//若栈不空,用e返回栈顶元素,并返回OK
{
if(S.top>S.base)
{
e=*(S.top-1); //栈顶元素赋值给e
return OK;
}
else
return ERROR;
}
void Push(SqStack &S,SElemType e) //插入元素e为栈顶新元素,
{
if(S.top-S.base==S.stacksize)//栈满
{
S.base=(SElemType *)realloc(S.base,(S.stacksize+STACK_INCREMENT)*sizeof(SElemType));
if(!S.base) //追加存贮空间失败
{
exit(OVERFLOW);
}
S.top=S.base+S.stacksize;
S.stacksize+=STACK_INCREMENT;
}
*(S.top)++=e; //将e入栈,成为新的栈顶元素,栈顶指针上移一个存贮单元

}
Status Pop(SqStack &S,SElemType &e) //若栈S不空,则删除S的栈顶元素,用e返回其值,并且返回OK
{
if(S.top==S.base)
return ERROR;
e=*--S.top;
return OK;
}
int main()
{
int j;
SqStack s;
SElemType e;
InitStack(s);
char str[100005];
int ipos=0,num=0,flag=0,num1,num2,result,num3;
gets(str);
for(int i=0;i<strlen(str);i++){
if('0'<=str[i]&&str[i]<='9'){
num=num*10+(str[i]-'0');
flag=1;
}

else if('*'<=str[i]&&str[i]<='/'){
if(flag)
Push(s,num);
Pop(s,num2);//弹出栈顶元素,将其值赋给e
//printf("弹出的栈顶元素为:%d\n",num1);
Pop(s,num1);
//printf("弹出的栈顶元素为:%d\n",num2);
switch (str[i]){
case '+':num3=num1+num2; break;
case '-':num3=num1-num2; break;
case '*':num3=num1*num2; break;
case '/':num3=num1/num2; break;

}
//printf("%d%c%d=%d ",num1,str[i],num2,num3);
Push(s,num3);
flag=num=0;
}

else {
if(flag)
Push(s,num);
flag=num=0;
}

}
GetTop(s,result); //将栈顶元素赋值给result
printf("%d\n",result);
return 0;

}输入一个中缀表达式,编程输出其后缀表达式,要求输出的后缀表达式的运算次序与输入的中缀表达式的运算次序相一致。为简单起见,假设输入的中缀表达式由+(加)、-(减)、×(乘)、/(除)四个运算符号以及左右圆括号和英文字母组成,其中算术运算符遵守先乘除后加减的运算规则。假设输入的中缀表达式长度不超过300个字符,且都是正确的,即没有语法错误,并且凡出现括号其内部一定有表达式,即内部至少有一个运算符号。
中缀表达式转后缀表达式的方法:

1.遇到操作数:直接输出(添加到后缀表达式中)

2.栈为空时,遇到运算符,直接入栈

3.遇到左括号:将其入栈

4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,括号不输出。

5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈

6.最终将栈中的元素依次出栈,输出。  

思路:照着题目模拟即可,这次偷懒使用了C++中STL栈的模板,不利于数据结构封装的函数的理解,但此程序中的其他函数的巧妙处理时需要好好学习的

#include <cstdio>
#include <stack>
#include <cstring>
using namespace std;
stack <char> s;
typedef int Status;
char str[300];
int judge(char a)
{
if(a=='+'||a=='-'||a=='*'||a=='/'||a==')'||a=='(')
return 1;
return 0;
}

int score(char a,int flag)
{
if(a=='+'||a=='-') return 1;
if(a=='*'||a=='/') return 2;
if(a=='('&&flag) return 0;//当'('在栈里的时候优先级设为0
if(a=='('&&!flag) return 3;//当'('不在栈里的时候优先级设为3
}
int main()
{
scanf("%s",str);
for(int i=0;i<strlen(str);i++)
{
if(!judge(str[i]))
printf("%c",str[i]);
else
{
if(s.empty())
s.push(str[i]);
else
{
if(str[i]==')'){
while(s.top()!='('&&!s.empty())
{
printf("%c",s.top());
s.pop();
}
s.pop(); //将( 出栈
continue;
}
while(!s.empty()&&score(str[i],0)<=score(s.top(),1))
{
printf("%c",s.top());
s.pop();
}
s.push(str[i]);

}

}
}
while(!s.empty())
{
printf("%c",s.top());
s.pop();
}
return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: