表达式计算
来源:互联网 发布:淘宝充话费可以退款么 编辑:程序博客网 时间:2024/05/16 18:58
转自http://blog.csdn.net/reidsc/article/details/54669433
这个题的思路就是先把中缀表达式转化为后缀表达式,然后用后缀表达式计算出式子的值
1.将中缀表达式转换为后缀表达式的方法:
(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
(2) 从左至右扫描中缀表达式;
(3) 遇到操作数时,将其压入S2,这里由于运算数可能大于10,所以如果数字后面一个符号是运算符,则将‘#’入S2栈充当分割线;
(4) 遇到运算符时有三种情况:
(4-1) 三种情况下直接入S1栈①S1为空②运算符为‘(’③运算符优先级比S1栈顶运算符的高;
(4-2)如果右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
(4-3) 若运算符优先级小于或等于S1栈顶运算符的优先级,则依次弹出S1栈顶元素,直到运算符的优先级大于S1栈顶运算符优先级;
(6) 重复步骤(2)至(5),直到表达式的最右边;
(7) 将S1中剩余的运算符依次弹出并压入S2;
(8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式。
运算符优先级: 左括号>(乘=除)>(加=减)>右括号 为了编程方便假定右括号优先级最小。
例:将 1 + ( ( 23 + 34 ) * 5 ) - 6转化为中缀表达式
扫描到的元素
S2(栈底->栈顶)
S1 (栈底->栈顶)
说明
1
1
空
数字,直接入栈,下一个元素是运算符#入栈
+
1
+
S1为空,运算符直接入栈
(
1
+ (
左括号,直接入栈
(
1
+ ( (
左括号,直接入栈
2
1 # 2
+ ( (
数字,直接入栈下一个元素不是运算符
3
1 # 2 3 #
+ ( (
数字,直接入栈,下一个元素是运算符#入栈
+
1 # 2 3 #
+ ( ( +
+优先级大于S1栈顶运算符,直接入栈.
3
1 # 2 3 # 3
+ ( ( +
数字,直接入栈,下一个元素不是运算符
4
1 # 2 3 # 3 4 #
+ ( ( +
数字,直接入栈,下一个元素是运算符#入栈
)
1 # 2 3 # 3 4 # +
+ (
右括号,弹出S1运算符直至遇到左括号,将弹出的元素压入S2中,丢弃一对括号
*
1 # 2 3 # 3 4 # +
+ ( *
*优先级大于S1栈顶运算符,直接入栈.
5
1 # 2 3 # 3 4 # + 5 #
+ ( *
数字,直接入栈,下一个元素是运算符#入栈
)
1 # 2 3 # 3 4 # + 5 # *
+
右括号,弹出S1运算符直至遇到左括号,将弹出的元素压入S2中,丢弃一对括号
-
1 # 2 3 # 3 4 # + 5 # * +
-
-与+优先级相同,因此弹出+,再压入-
6
1 # 2 3 # 3 4 # + 5 # * + 6 #
-
数字,直接入栈,下一个元素是运算符#入栈
到达最右端
1 # 2 3 # 3 4 # + 5 # * + 6 # -
空
S1中剩余的运算符弹出并压入S2
所以计算结果为:1 # 2 3 # 3 4 # + 5 # * + 6 # -
2.后缀表达式计算方法:
(1)定义一个int栈S3,定义一个整形数组num用来存储大于10的数字便于计算,从左至右扫描表达式。
(2)遇到数字时:
(2-1)若数字后面一个元素不是#(数字后面只可能是#或数字)则将数字字符转化为数字存在num[ ]数组中;
(2-2)若数字后面一个元素是#,将num数组中保存的数字算出来并压入S3栈中。
(3)遇到运算符时,弹出S3栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
例如后缀表达式“1 # 2 3 # 3 4 # + 5 # * + 6 # -”:
扫描到的元素
S3(栈底->栈顶)
num[ ](从左到右下标从0递增)
说明
1
1
1
数字,下一个元素为#故将num中算出来压入S3中
#
1
1
#,跳过,(下一次赋值从num[0]开始)
2
1
2
数字,下一个元素不为#故将元素转化为数字存入num中
3
1 23
2 3
数字,下一个元素为#故将num中算出来压入S3中
#
1 23
2 3
#,跳过
3
1 23
3 3
数字,下一个元素不为#故将元素转化为数字存入num中,注意从num[0]开始
4
1 23 34
3 4
数字,下一个元素为#故将num中算出来压入S3中
#
1 23 34
3 4
#,跳过
+
1 57
3 4
+,弹出S3栈顶两元素,进行加法计算后压入栈中
5
1 57 5
5 4
数字,下一个元素为#故将num中算出来压入S3中
#
1 57 5
5 4
#,跳过
*
1 285
5 4
*,弹出S3栈顶两元素,进行乘法计算后压入栈中
+
286
5 4
+,弹出S3栈顶两元素,进行加法计算后压入栈中
6
286 6
6 4
数字,下一个元素为#故将num中算出来压入S3中
#
286 6
6 4
#,跳过
-
280
6 4
-,弹出S3栈顶两元素,进行减法计算后压入栈中。
//#include "cxf_acm.h"
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <stack>
using namespace std;
typedef long long ll;
#define PI 3.1415926535897932
#define E 2.718281828459045
#define INF 0x3f3f3f3f
#define mod 123456789
const int M=1005;
int n,m;
int cnt;
int sx,sy,sz;
char mp[M];
int pa[M*10],rankk[M];
int head[M*6],vis[M*10];
double dis[M][10];
ll prime[M*1000];
bool isprime[M*1000];
int lowcost[M],closet[M];
//char st1[5050],st2[5050];
int len[M*6];
typedef pair<int ,int> ac;
vector<int> g[M*10];
ll dp[10005][205];
int has[105][105];
int month[13]= {0,31,59,90,120,151,181,212,243,273,304,334,0};
int dir[8][2]= {{0,1},{0,-1},{-1,0},{1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
void getpri()
{
ll i;
int j;
cnt=0;
memset(isprime,false,sizeof(isprime));
for(i=2; i<1000000LL; i++)
{
if(!isprime[i])prime[cnt++]=i;
for(j=0; j<cnt&&prime[j]*i<1000000LL; j++)
{
isprime[i*prime[j]]=1;
if(i%prime[j]==0)break;
}
}
}
ll qk_mul(ll a,ll b,ll mo)
{
ll t=0;
while(b)
{
if(b&1)
t=(t+a)%mo;
a=(a<<1)%mo;
b>>=1;
}
t%=mo;
return t;
}
ll qk_mod(ll a,ll b,ll mo)
{
ll ans=1;
while(b)
{
if(b&1) ans=qk_mul(ans,a,mo);
a=qk_mul(a,a,mo);
b>>=1;
}
ans%=mo;
return ans;
}
int gcd(int a,int b)
{
return b == 0 ? a : gcd(b, a%b);
}
int lcm(int a,int b)
{
return a*b/gcd(a,b);
}
int findx(int t)
{
if(t!=pa[t])
pa[t]=findx(pa[t]);
return pa[t];
}
void unionx(int x,int y)
{
x=findx(x);
y=findx(y);
if(x!=y)
{
pa[y]=x;
}
}
//queue<nodei *>qu;
void init()
{
for(int i=0; i<101; i++)
pa[i]=i;
}
int heap[100005];
void push(int x)
{
int i=++sz;
while(i>1) //i>0
{
int p=i/2; //(i-1)/2
if(heap[p]<=x)break;
heap[i]=heap[p];
i=p;
}
heap[i]=x;
/* a[++sz] = x;
int t = a[sz];
int tson = sz;
while( (tson > 1)&&( a[tson/2] > t))
{
a[tson] = a[tson/2];
tson = tson/2;
}
a[tson] = x;
*/
}
int pop()
{
int ret=heap[1];//int ret=a[0]
int x=heap[sz--];//a[--sz]
int i=1;// i=0
while(2*i<sz) //2*i+1
{
int a=i*2,b=i*2+1;
if(b<sz&&heap[b]<heap[a])a=b;
if(heap[a]>=x)break;
heap[i]=heap[a];
i=a;
}
heap[i]=x;
return ret;
}
int lowbit(int i)
{
return i&(-i);
}
void add(int i,int j,ll v)//修改值并向父节点修改
{
while(i<=cnt)
{
dp[i][j]+=v;//c[i]开始都是0,每经过一个数,它的c[i]+1表示c[i]
i+=lowbit(i);
}
}
ll sum(int i,int j)//求和
{
ll s=0;
while(i>=1)
{
s=(s+dp[i][j])%mod;
i-=lowbit(i);
}
return s;
}
char pre[7][7]={
{'>','>','<','<','<','>','>'},
{'>','>','<','<','<','>','>'},
{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},
{'<','<','<','<','<','=','0'},
{'>','>','>','>','0','>','>'},
{'<','<','<','<','<','0','='}};
char procede(char a,char b)
{
int i,j;
switch(a)
{
case'+':i=0;break;
case'-':i=1;break;
case'*':i=2;break;
case'/':i=3;break;
case'(':i=4;break;
case')':i=5;break;
case'#':i=6;break;
}
switch(b)
{
case'+':j=0;break;
case'-':j=1;break;
case'*':j=2;break;
case'/':j=3;break;
case'(':j=4;break;
case')':j=5;break;
case'#':j=6;break;
}
return pre[i][j];
}
int operation(int m,int n,char x)
{
if(x=='+')
return m+n;
if(x=='-')
return n-m;
if(x=='*')
return m*n;
if(x=='/')
return n/m;
}
int main()
{
int i,j,t;
char c;
stack<int>st1;
stack<char>st2;
st2.push('#');
scanf("%s",mp);
int l=strlen(mp);
mp[l]='#',mp[l+1]='\0';
//puts(mp);
c=mp[0];
t=1;
while(c!='#'||st2.top()!='#')
{
i=0;
if(c>='0'&&c<='9')
{
while(c>='0'&&c<='9')
{
i=i*10+(c-'0');
c=mp[t++];
}
st1.push(i);
}
else
{
switch(procede(st2.top(),c))
{
case'=':
st2.pop();
c=mp[t++];
break;
case'<':
st2.push(c);
c=mp[t++];
break;
case'>':
char tt=st2.top();st2.pop();
int x=st1.top();st1.pop();
int y=st1.top();st1.pop();
st1.push(operation(x,y,tt));
break;
}
}
}
printf("%d\n",st1.top());
return 0;
}
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 计算表达式
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算
- 表达式计算 .
- 计算表达式
- 计算表达式
- 表达式计算
- 表达式计算
- 表达式计算
- SpringBoot集成log4j
- 基于Java实现的一个简单计算器
- POJ3204 最大流
- Why Namespace?
- 三月英语-丘陵
- 表达式计算
- HDFS的shell(命令行客户端)操作
- 访问外网 ML2 的配置
- lintcode 167 链表求和
- 小白学 GIT
- 创建外网 ext_net
- Json和JsonP及ajax跨域的解决办法
- 外网访问原理分析
- 华为2016研发工程师编程题---删数