转载:https://blog.csdn.net/INCINCIBLE/article/details/51151222?locationNum=5&fps=1
题目链接:http://noi.openjudge.cn/ch0303/6263/
描述
输入一个布尔表达式,请你输出它的真假值。
比如:( V | V ) & F & ( F | V )
V表示true,F表示false,&表示与,|表示或,!表示非。
上式的结果是F
( V | V ) & F & ( F| V) !V | V & V & !F & (F | V ) & (!F | F | !V & V) (F&F|V|!V&!F&!(F|F&V))样例输出
F V V
分析:
原理很简单,将中缀表达式转化为前缀表达式在计算,只是代码实现比较麻烦。
中缀转前缀的步骤如下:
(1) 首先构造一个
运算符栈(也可放置括号),运算符(以括号分界点)在栈内遵循越往栈顶优先级不降低的原则进行排列。
(2)从右至左扫描
中缀表达式,从右边第一个字符开始判断:
如果当前
字符是数字,则分析到数字串的结尾并将数字串直接输出。
如果是运算符,则比较
优先级。如果当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),则将
运算符直接入栈;否则将栈顶运算符
出栈并输出,直到当前运算符的优先级大于等于栈顶运算符的优先级(当栈顶是括号时,直接入栈),再将当前运算符入栈。
如果是括号,则根据括号的方向进行处理。如果是右括号,则直接入栈;否则,遇左括号前将所有的运算符全部出栈并输出,遇右括号后将左右的两括号一起删除。
(3) 重复上述操作(2)直至扫描结束,将栈内剩余运算符全部出栈并输出,再逆缀输出字符串。
中缀表达式也就转换为前缀表达式了。
代码:
- #include<iostream>
- #include<cstdio>
- #include<algorithm>
- #include<queue>
- #include<stack>
- #include<cstring>
- using namespace std;
- char calculate(char x, char y,char oper ){ // 计算 x oper y
- bool a=(x=='V'),b=(y=='V'),ans;
- if(oper=='|')ans=(a||b);
- else if(oper=='&')ans=(a&&b);
- return ans?'V':'F';
- }
- char reverse(char x){
- if(x=='V')return 'F';
- return 'V';
- }
- int main(){
- string in;
- int i,j,len;
- while(getline(cin,in)){
- stack< char > Oper,num; //oper保存运算符,num保存运算结果
- queue< char > s; // s就是前缀表达式
- len=in.length();
- i=len;
- in=" "+in;
- while(i>0){ // 从右往左,中缀表达式转 前缀表达式
- if(in[i]==' '){
- i--;continue;
- }
- else if(isalpha(in[i]))s.push(in[i--]);
- else if(in[i]=='!') //最高级的运算,直接进入表达式
- s.push(in[i--]);
- else{
- if(in[i]=='&'||in[i]=='|'||in[i]==')') //低级运算,进栈
- Oper.push(in[i--]);
- else if(in[i]=='('){ //一个括号结束,弹出中间的所有运算符
- while(Oper.top()!=')'){
- s.push(Oper.top());
- Oper.pop();
- }
- Oper.pop();i--;
- }
- }
- }
- while(!Oper.empty()) //栈中剩下的运算符
- s.push(Oper.top()),Oper.pop();
- while(!s.empty()){ //计算前缀表达式
- char ch=s.front();s.pop();
- if(isalpha(ch))num.push(ch);
- else Oper.push(ch);
- if(!num.empty()&&!Oper.empty()&&Oper.top()=='!'){ //单目运算符‘!’;
- char x=num.top();
- num.pop();Oper.pop();
- num.push(reverse(x));
- }
- else if(num.size()>=2&&!Oper.empty()){ //双目运算符
- char oper=Oper.top(),x,y;
- Oper.pop();
- x=num.top();num.pop();
- y=num.top();num.pop();
- num.push(calculate(x,y,oper));
- }
- }
- cout<<num.top()<<endl;
- }
- }