先说简单的算术表达式的求值
别慌,真正的算术表达式求值在后面,这只是前奏
题目来源:HDU http://acm.hdu.edu.cn/showproblem.php?pid=1237
★这题因为没有括号,所以很简单,甚至不需要栈和队列(我就没用)
相关知识:
算是小学知识了叭,一个规律不知道你们记得否:如果没有括号,算术表达式一定是一个数一个运算符交替排列的。
思路:
首先输入一个数,然后接着一定是 一个符号+一个数 的规律直到最后,在过程中,如果有乘除就运算,有减就把数变为相反数,有加就跳到下一个数开始。最后肯定都是加号,把所有数加起来即为答案。
代码:
#include<stdio.h>
#include<string.h>
int main()
{
double num[200];
int t;
while(~scanf("%d",&t))
{
char c;
int l=0,i;
double sum=t*1.0;
if(t==0&&(c=getchar())=='\n') return 0;
while((c=getchar())!='\n')
{
if(c=='*') {scanf("%d",&t); sum*=t;}
else if (c=='/') {scanf("%d",&t); sum/=t;}
else if (c=='+') {scanf("%d",&t); num[l++]=sum; sum=t*1.0;}
else if (c=='-') {scanf("%d",&t); num[l++]=sum; sum=-t*1.0;}
}
num[l++]=sum;
double ans=0;
for(i=0;i<=l-1;i++) ans+=num[i];
printf("%.2lf\n",ans);
}
}
是不是这题的一股清流233
话不多说,接下来是重头戏
题目来源:WUSTOJ http://acm.wust.edu.cn/problem.php?id=1642&soj=0
★因为有括号,所以再也没有那种骚操作 的规律了,老老实实用栈写(至少我不会其他操作了 )
相关知识:
首先 括号优先级最高,乘除其次,加减最低,废话
然后要知道,左括号绝大多数都在运算符右边(或者第一个字符就是左括号)
最后你要会把字符串里面的数准确的取出,这也是一个难点
话不多说,看我表演,show time~
思路:
定义两个栈,sign存放字符,num存放数。先读字符串,然后从头开始循环遍历每个字符。如果是+,把1压入sign;如果是-,把2压入sign;如果是*,把3压入sign;如果是/,把4压入sign;如果是(,把0压入sign;如果是数字,把它压入num(并不是简单的直接压,我只是简略的说 ),然后如果sign不为空,并且下一个字符不为数字(如果是数字,说明当前正在读取的数没有读完,好好理解这里),这时去sign栈顶,如果是* /,进行sum1运算,是-,进行sum2运算;如果是),就一直运算到sign栈顶为(,并把(给弹出,还没完,此时可能需要进行sum1,sum2运算。最后应该还会剩下一些数,但是符号一定只剩下+了,把他们简单的处理掉~最后答案就是num栈顶。
上面是较详细解读我的代码,从总体看,我的代码分为3步。解决();解决 / -;解决+*
注意:
别忘了,最后还保留了一个num没有弹出,把它处理一下。
代码:
#include<bits/stdc++.h>
using namespace std;
stack<int> sign;
stack<int> num; //双栈
void sum1(int a) //乘除法
{
int x=num.top(); num.pop();
int y=num.top(); num.pop();
if(a==3) y=y*x;
if(a==4) y=y/x;
num.push(y);
sign.pop();
}
void sum2() //变为相反数
{
int x=num.top(); num.pop();
x=-x;
sign.pop();
num.push(x);
sign.push(1);
}
int main()
{
string s;
while(cin>>s){
int len=s.length();
while(sign.size()) sign.pop(); //清空栈,这是我注意事项里面的操作
while(num.size()) num.pop();
for(int i=0;i<len;i++){
if(s[i]>='0'&&s[i]<='9'){
if(i&&s[i-1]>='0'&&s[i-1]<='9'){
int a=num.top();
num.pop();
a=a*10+s[i]-'0';
num.push(a);
}
else num.push(s[i]-'0'); //完整取出数
if(sign.size()){
if(i==len-1||((i<len-1)&&(s[i+1]<'0'||s[i+1]>'9'))){
int a=sign.top();
if(a==3||a==4) sum1(a);
else if(a==2) sum2();
}
}
}
else if(s[i]=='+') sign.push(1);
else if(s[i]=='-') sign.push(2);
else if(s[i]=='*') sign.push(3);
else if(s[i]=='/') sign.push(4);
else if(s[i]=='('){
sign.push(0);
if(s[i+1]=='-') num.push(0); //如果括号下一个字符是-,则多补一个0,可能没有这种情况---》 (-1) 但是万一有呢?
}
else if(s[i]==')'){
int a=sign.top();
while(a){
int x=num.top(); num.pop();
int y=num.top(); num.pop();
if(a==1) y=y+x;
num.push(y);
sign.pop();
a=sign.top();
}
sign.pop();
if(sign.size()){
a=sign.top();
if(a==3||a==4) sum1(a);
else if(a==2) sum2();
else continue;
}
}
}
while(num.size()>1){
int a=sign.top();
sign.pop();
int x=num.top(); num.pop();
int y=num.top(); num.pop();
if(a==1) y=y+x;
num.push(y);
}
cout<<num.top()<<endl;
}
}
我觉得我的代码很简单了,我看别人好多都是100+,我才80多行 。当然,人外有人,大佬看到就见笑了233.