NOI:6263 布尔表达式

转载: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

输入 输入包含多行,每行一个布尔表达式,表达式中可以有空格,总长度不超过1000 输出 对每行输入,如果表达式为真,输出"V",否则出来"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)直至扫描结束,将栈内剩余运算符全部出栈并输出,再逆缀输出字符串。 中缀表达式也就转换为前缀表达式了。
代码:
 
[cpp]  view plain  copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<algorithm>  
  4. #include<queue>  
  5. #include<stack>  
  6. #include<cstring>  
  7. using namespace std;  
  8. char calculate(char x, char y,char oper ){ // 计算 x oper y   
  9.     bool a=(x=='V'),b=(y=='V'),ans;  
  10.     if(oper=='|')ans=(a||b);  
  11.     else if(oper=='&')ans=(a&&b);  
  12.     return ans?'V':'F';  
  13. }  
  14. char reverse(char x){  
  15.     if(x=='V')return 'F';  
  16.     return 'V';  
  17. }  
  18. int main(){  
  19.     string in;  
  20.     int i,j,len;  
  21.       
  22.     while(getline(cin,in)){  
  23.         stack< char > Oper,num; //oper保存运算符,num保存运算结果   
  24.         queue< char > s;      //  s就是前缀表达式   
  25.         len=in.length();  
  26.         i=len;  
  27.         in=" "+in;  
  28.         while(i>0){  // 从右往左,中缀表达式转 前缀表达式   
  29.             if(in[i]==' '){  
  30.                 i--;continue;  
  31.             }  
  32.             else if(isalpha(in[i]))s.push(in[i--]);  
  33.             else if(in[i]=='!')     //最高级的运算,直接进入表达式   
  34.                 s.push(in[i--]);  
  35.             else{  
  36.                 if(in[i]=='&'||in[i]=='|'||in[i]==')')  //低级运算,进栈   
  37.                 Oper.push(in[i--]);  
  38.                 else if(in[i]=='('){  //一个括号结束,弹出中间的所有运算符   
  39.                     while(Oper.top()!=')'){  
  40.                         s.push(Oper.top());  
  41.                         Oper.pop();  
  42.                     }  
  43.                     Oper.pop();i--;  
  44.                 }  
  45.             }  
  46.         }  
  47.     while(!Oper.empty())    //栈中剩下的运算符   
  48.         s.push(Oper.top()),Oper.pop();  
  49.     while(!s.empty()){      //计算前缀表达式   
  50.         char ch=s.front();s.pop();  
  51.         if(isalpha(ch))num.push(ch);  
  52.         else Oper.push(ch);  
  53.         if(!num.empty()&&!Oper.empty()&&Oper.top()=='!'){  //单目运算符‘!’;   
  54.             char x=num.top();  
  55.             num.pop();Oper.pop();  
  56.             num.push(reverse(x));  
  57.         }  
  58.         else if(num.size()>=2&&!Oper.empty()){   //双目运算符   
  59.             char oper=Oper.top(),x,y;  
  60.             Oper.pop();  
  61.             x=num.top();num.pop();  
  62.             y=num.top();num.pop();  
  63.             num.push(calculate(x,y,oper));  
  64.         }  
  65.     }  
  66.     cout<<num.top()<<endl;  
  67. }  
  68. }  

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值