问题 A: 简单计算器
时间限制: 1 Sec 内存限制: 32 MB
提交: 1055 解决: 442
[提交][状态][讨论版][命题人:外部导入]
题目描述
读入一个只包含 +, -, *, / 的非负整数计算表达式,计算该表达式的值。
输入
测试输入包含若干测试用例,每个测试用例占一行,每行不超过200个字符,整数和运算符之间用一个空格分隔。没有非法表达式。当一行中只有0时输入结束,相应的结果不要输出。
输出
对每个测试用例输出1行,即该表达式的值,精确到小数点后2位。
样例输入
30 / 90 - 26 + 97 - 5 - 6 - 13 / 88 * 6 + 51 / 29 + 79 * 87 + 57 * 92
0
样例输出
人脑熟悉中缀表达式,而计算机熟悉前缀后缀表达式,商业计算机都用后缀表达式,因此先将中缀表达式(输入的字符串)转换为后缀表达式,然后再进行计算
前缀后缀参考
后缀表达式参考2
后缀表达式
简介
后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后
比如:3 4 + 5 × 6 -
后缀表达式计算机求值
与前缀表达式类似,只是顺序是从左至右:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果
例如后缀表达式“3 4 + 5 × 6 -”:
- 从左至右扫描,将3和4压入堆栈;
- 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
- 将5入栈;
- 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
- 将6入栈;
- 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。
将中缀表达式转换为后缀表达式
与转换为前缀表达式相似,步骤如下:
- 初始化两个栈:运算符栈s1和储存中间结果的栈s2;
- 从左至右扫描中缀表达式;
- 遇到操作数时,将其压s2;
- 遇到运算符时,比较其与s1栈顶运算符的优先级:
- 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
- 否则,若优先级比栈顶运算符的高,也将运算符压入s1
- 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较;(循环)
- 遇到括号时:
- 如果是左括号“(”,则直接压入s1;
- 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃;
- 重复步骤2至5,直到表达式的最右边;
- 将s1中剩余的运算符依次弹出并压入s2;
- 依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)
例如,将中缀表达式“1+((2+3)×4)-5”转换为后缀表达式的过程如下:
扫描到的元素s2(栈底->栈顶)s1 (栈底->栈顶)说明11空数字,直接入栈+1+s1为空,运算符直接入栈(1+ (左括号,直接入栈(1+ ( (同上21 2+ ( (数字+1 2+ ( ( +s1栈顶为左括号,运算符直接入栈31 2 3+ ( ( +数字)1 2 3 ++ (右括号,弹出运算符直至遇到左括号×1 2 3 ++ ( ×s1栈顶为左括号,运算符直接入栈41 2 3 + 4+ ( ×数字)1 2 3 + 4 ×+右括号,弹出运算符直至遇到左括号-1 2 3 + 4 × +--与+优先级相同,因此弹出+,再压入-51 2 3 + 4 × + 5-数字到达最右端1 2 3 + 4 × + 5 -空s1中剩余的运算符
因此结果为“1 2 3 + 4 × + 5 -”
#include<iostream>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<cctype>//isdigit()
using namespace std;
struct node{
double num;//当前节点操作数值
char op;//当前节点操作符
bool flag;//当前节点到底是操作符还是操作数 true:操作数 false:运算符
};
string str;//记录输入的表达式
stack<node> s;//运算符栈
queue<node> q;//操作数兼后缀表达式中间结果队列(运行完为最后的结果)
map<char,int> mp;//用map记录运算符优先级别
//中缀表达式转后缀表达式
void Change(){
node temp; //存储当前临时节点
for(int i=0;i<str.length();){
if(isdigit(str[i])){//是操作数
temp.flag=true;//操作数
temp.num=str[i++]-'0';
while(!str.empty()&&isdigit(str[i])){//多位数字 string也有empty
temp.num=temp.num*10+(str[i]-'0');
i++;
}
q.push(temp);//如操作数队列
}else{//是运算符
temp.flag=false;
temp.op=str[i++]; //注意小于等于不是小于
while(!s.empty()&&mp[s.top().op]>=mp[temp.op]){//优先级低于运算符栈顶元素 ★★
q.push(s.top());
s.pop();
}
//然后才能将temp压入运算符栈
s.push(temp);//压入运算符栈 是s.push不是q.push千万别写错了 ★★
}
}
//★★
//若最后运算符栈还有运算符,直接全部压入后缀表达式
while(!s.empty()){
q.push(s.top());
s.pop();
}
//最终q里的就是最后的后缀表达式
}
double cal(){
double x1,x2,ans;
node temp;
stack<double> s;//运算数 中间结果栈 最终结果栈
// while(!s.empty()) s.pop();//初始化清空栈
while(!q.empty()){
temp=q.front();
q.pop();//提前pop()否则忘了陷入死循环
if(temp.flag){//运算数
s.push(temp.num);
}else{//运算符
x2=s.top();s.pop();
x1=s.top();s.pop();//注意x2 与 x1的顺序 先出栈的为第二操作数 ★★
switch(temp.op){
case '+':
ans=x1+x2;
break;
case '-':
ans=x1-x2;
break;
case '*':
ans=x1*x2;
break;
case '/':
ans=x1/x2;
break;
}
s.push(ans);//新操作数入栈
}
}
//最终的结果就是答案
return s.top();
}
int main(){
mp['+']=mp['-']=0;
mp['*']=mp['/']=1;
while(getline(cin,str)&&str!="0"){
for(string::iterator it=str.begin();it!=str.end();it++){
if(*it==' ') str.erase(it);
}
// cout<<str<<endl;
Change();
printf("%.2f\n", cal());
}
return 0;
}
问题 B: Problem E
时间限制: 1 Sec 内存限制: 32 MB
提交: 620 解决: 210
[提交][状态][讨论版][命题人:外部导入]
题目描述
请写一个程序,判断给定表达式中的括号是否匹配,表达式中的合法括号为”(“, “)”, “[", "]“, “{“, ”}”,这三个括号可以按照任意的次序嵌套使用。
输入
有多个表达式,输入数据的第一行是表达式的数目,每个表达式占一行。
输出
对每个表达式,若其中的括号是匹配的,则输出”yes”,否则输出”no”。
样例输入
4
[(d+f)*{}]
[(2+3))
()}
[4(6]7)9
样例输出
此题简单,但注意()}}]]]]栈提前空了的清空 不判断的话,()会运行报错
#include<iostream>
#include<stack>
#include<string>
#include<map>
using namespace std;
string str;
map<char,char> mp;
bool isLegal(){
stack<char> s;
for(int i=0;i<str.length();i++){
if(str[i]=='('||str[i]=='['||str[i]=='{'){
s.push(str[i]);
}else if(str[i]==')'||str[i]==']'||str[i]=='}'){
//此时若栈提前空了 也非法 ★★
if(!s.empty()&&s.top()==mp[str[i]]) s.pop();
else{
return false;
}
}
}
if(!s.empty()) return false;
else return true;
}
int main(){
mp[']']='[';
mp[')']='(';
mp['}']='{';
int T;
while(cin>>T){
while(T--){
cin>>str;
if(isLegal()) cout<<"yes\n";
else cout<<"no\n";
}
}
return 0;
}