码迷,mamicode.com
首页 > 其他好文 > 详细

利用栈求逻辑运算表达式的真值

时间:2015-03-30 09:29:30      阅读:180      评论:0      收藏:0      [点我收藏+]

标签:

今天浙江理工校赛的D题。

比赛结束后在网上看了文章才做出来的。


Problem D: 逻辑运算

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 248  Solved: 36

Description

 还记得大学里学过的模电么,今天就让我们将与或非变成一道题吧。

给你一个与或非的表达式,求出这个表达式的值,表达式总共有八种字符。

三种逻辑运算符按照优先级排列如下。

‘!’:表示取反。

‘&’:逻辑与。

‘|’:逻辑或。

两个字符‘T’,‘F‘分别表示true和 false。

另外还有左右括号,空格三种字符。跟一般的表达式一样,括号可以改变优先级。

 

Input

每组数据输入一行字符串,字符串长度小于等于100.

Output

 输出一个数0或1,表示逻辑表达式的答案。

Sample Input

T

Sample Output

1


用2个栈,一个存储运算符,一个存储运算的数字。

对于连个相继出现的操作符θ1和θ2 有三种关系:大于、等于和小于。由此可以列出“+-*/”之间的优先级。如下表:


     !      &     |      (      )      #

!    >     >     >     <     >     >

&   <     >     >     <     >     >

|    <     <     >     <     >     >

(    <     <     <     <     =     >

)    >     >     >     <     >     >

#   <     <     <     <     >     =


为了算法简洁,在表达式的左边和右边虚设一个“#”,这一对“#”表示一个表达式求值完成。

“(”    =     “)”  当一对括号相遇时表示括号内已运算完成。

“)”和“(”、“#”和“(”、“(”和“#”无法相继出现如果出现则表达式出现语法错误。

为实现优先算法,可以使用两个工作栈,一个是Q,用于寄存运算符,一个是P,用于寄存运算数和运算结果。



算法基本思路。

首先置操作数栈为空栈,表达式起始符为“#”为栈底元素。

依次读入表达式中的每个字符,若是操作数则进Q栈,若是运算符则和Q栈的栈顶运算符比较优先权作相应操作,直至整个表达式求值完毕(Q栈顶元素和当前读入的字符均为“#”)

代码实现:

<pre name="code" class="cpp"><span style="font-size:14px;">#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
using namespace std;

const double PI = acos(-1.0);
const double e = 2.718281828459;
const double eps = 1e-8;
const int MAXN = 110;
char s[MAXN];
char opset[6] = {'!','&','|','(',')','#'};
char prio[6][6] =
{
    '>', '>', '>', '<', '>', '>',
    '<', '>', '>', '<', '>', '>',
    '<', '<', '>', '<', '>', '>',
    '<', '<', '<', '<', '=', '>',
    '>', '>', '>', '<', '>', '>',
    '<', '<', '<', '<', '>', '=',
};

//找到对应运算符在 opset 数组的下标
int findindex(char op)
{
    for(int i = 0; i < 6; i++)
    {
        if(opset[i] == op)
            return i;
    }
}

//比较Q栈顶元素与当前s[i]中运算符的优先级
char compare(char a, char b)
{
    int x = findindex(a);
    int y = findindex(b);
    return prio[x][y];
}

//计算 x y 在op运算符下的结果
int calc(int x, int y, char op)
{
    if(op == '|')
        return x|y;
    if(op == '&')
        return x&y;
    return 0;
}

int main()
{
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    while(scanf("%s", s) != EOF)
    {
        int lens = strlen(s);
        s[lens] = '#';   // s 数组尾部存为'#'
        s[lens+1] = '\0';
        int t, x, y;
        char op;
        int i = 0;
        stack<int>P;  // 用于存储运算数,整数元素
        stack<char>Q;  //用于存储运算符号,字符元素
        Q.push('#');  //把栈底存为 '#'
        while(s[i]!='#' || Q.top()!='#')
        {
            //当s数组读到末尾,且Q已经读到栈底,说明全部运算结束
            if(s[i]=='T' || s[i]=='F')
            {
                //读取到 T 或 F, 转化为0 或 1入栈
                if(s[i] == 'T')
                    t = 1;
                else
                    t = 0;
                P.push(t);
                i++;
            }
            else if(s[i] != ' ')
            {
                //由于输入的字符串包含空格,所以要空格要略过
                switch(compare(Q.top(), s[i]))
                {
                case '<':  // 栈顶元素优先级低,则当前元素入栈
                    Q.push(s[i]);
                    i++;
                    break;
                case '=': // 左右括号匹配,脱括号并接收下一字符
                    Q.pop();
                    i++;
                    break;
                case '>':  // 退栈并将运算结果入栈
                    if(Q.top() == '!')
                    {   // 栈顶元素为 !,单目操作符
                        x = P.top();
                        P.pop();
                        P.push(!x);
                        Q.pop();
                    }
                    else
                    {   // 栈顶元素不是 !
                        x = P.top();
                        P.pop();
                        y = P.top();
                        P.pop();
                        op = Q.top();
                        Q.pop();    //计算结果并入栈
                        P.push(calc(x, y, op));
                    }
                    break;
                }
            }
        }
        int ans = P.top();
        cout<<ans<<endl;
    }
    return 0;
}
</span>




利用栈求逻辑运算表达式的真值

标签:

原文地址:http://blog.csdn.net/u014028317/article/details/44731545

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!