茴字的确有四种写法- -

来源:互联网 发布:php new class 返回值 编辑:程序博客网 时间:2024/06/02 17:17

昨天做了一下POJ2106,很明显就是一道表达式求值的题:中序转化为后序,然后求值。三年前准备考研的时候不说闭着眼睛至少很快我也能写出来,但是这几年貌似待废了,昨天想了很久还看了书才想起来算法…真丢人。在校内发了这条状态,师兄回复说“表达式求值有四种写法,你都会么?”当时我过度紧张blabla了两句才发现是在茴香豆= =不过最后发现这道题还真的(至少)有四种写法


1 表达式求值,用栈

比较中规中矩的写法。贴个自己的。有bug但是不妨碍过- -

#include <iostream>#include <stack>#include <string>using namespace std;int getPrio(char a){switch (a) {case '|':return 1;break;case '&':return 2;break;case '!':return 3;break;default:return 0;break;}}int main (int argc, char * const argv[]) {string expr;int nExpr = 1;while (getline(cin, expr)) {string::iterator exprItr;string postfix;stack<char> operandStack;stack<char> operatorStack;for (exprItr = expr.begin(); exprItr != expr.end(); ++exprItr) {char tempChar = *exprItr;if (tempChar == 'V' || tempChar == 'F') {postfix.push_back(tempChar);}else if (tempChar == '(') {operatorStack.push(tempChar);}else if (tempChar == ')') {if (operatorStack.empty()) {break; //parenthesis don't match.}while (true) {char topOperator = operatorStack.top();operatorStack.pop();if (topOperator == '(')break;else {postfix.push_back(topOperator);}}}else if (tempChar == '&' || tempChar == '|') {while (!operatorStack.empty() && operatorStack.top() != '(' && getPrio(operatorStack.top()) >= getPrio(tempChar)) {postfix.push_back(operatorStack.top());operatorStack.pop();}operatorStack.push(tempChar);}else if (tempChar == '!') {while (!operatorStack.empty() && operatorStack.top() != '(' && getPrio(operatorStack.top()) > getPrio(tempChar)) {postfix.push_back(operatorStack.top());operatorStack.pop();}operatorStack.push(tempChar);}}while (!operatorStack.empty()) {postfix.push_back(operatorStack.top());operatorStack.pop();}//cout << postfix << endl;for (exprItr = postfix.begin(); exprItr != postfix.end(); ++exprItr) {char tempChar = *exprItr;if (tempChar == 'V' || tempChar == 'F') {operandStack.push(tempChar);}else if (tempChar == '&') {char rightOperand = operandStack.top();operandStack.pop();char leftOperand = operandStack.top();operandStack.pop();if (leftOperand == 'V' && rightOperand == 'V') {leftOperand = 'V';} else {leftOperand = 'F';}operandStack.push(leftOperand);}else if (tempChar == '|') {char rightOperand = operandStack.top();operandStack.pop();char leftOperand = operandStack.top();operandStack.pop();if (leftOperand == 'F' && rightOperand == 'F') {leftOperand = 'F';} else {leftOperand = 'V';}operandStack.push(leftOperand);}else if (tempChar == '!') {char operand = operandStack.top();operandStack.pop();if (operand == 'V')operand = 'F';else {operand = 'V';}operandStack.push(operand);}}cout << "Expression " << nExpr << ": " << operandStack.top() << endl;nExpr ++;}    return 0;}



2 师弟用递归写了一个表达式求值

/*POJ 2106±í´ïʽÇóÖµ¡£×Ô¼ºÐ´ÁËÒ»¸öºÜʺµÄµÝ¹é½â·¨£¬ËٶȺÜÂý¡£ÓÃLL1ÎÄ·¨¿ÉÒÔÇáÈ¡*/#include <string>#include <iostream>using namespace std;bool calc(string s);string trim(string s){    int pos1 = 0;    int pos2 = s.length() - 1;    while (s[pos1] == ' ')        pos1++;    while (s[pos2] == ' ')        pos2--;    return s.substr(pos1, pos2 - pos1 + 1);}int findmatchedbrace(int start, string s){    int pos = start;    while (s[pos] != '(' && s[pos] != ')')    {        pos++;    }    if (s[pos] == ')')        return pos;    pos = findmatchedbrace(pos + 1, s);    return findmatchedbrace(pos + 1, s);}bool calcand(string s){    int pos = 0;    int start = pos;    string str = trim(s);    string ands[100];    int cnt = 0;    while (pos < str.length())    {        if (str[pos] == '(')        {            pos = findmatchedbrace(pos + 1, str);        }        else if (str[pos] == '&')        {            ands[cnt++] = str.substr(start, pos - start);            start = pos + 1;            pos = start - 1;        }        pos++;    }    ands[cnt++] = str.substr(start, pos - start);    if (cnt == 1)    {        if (str[0] == '!')            return !calc(str.substr(1, str.length() - 1));        else if (str[0] == '(')        {            int match = findmatchedbrace(1, str);            return calc(str.substr(1, match - 1));        }    }    for (int i = 0; i < cnt; i++)    {        if (!calc(ands[i]))            return false;    }    return true;}bool calc(string s){    string str = trim(s);    if (str.length() == 1)    {        return str == "V";    }    int pos = 0;    string ors[100];    int cnt = 0;    int start = pos;    while (pos < str.length())    {        if (str[pos] == '(')        {            pos = findmatchedbrace(pos + 1, str);        }        else if (str[pos] == '|')        {            ors[cnt++] = str.substr(start, pos - start);            start = pos + 1;            pos = start - 1;        }        pos++;    }    ors[cnt++] = str.substr(start, pos - start);    if (cnt == 1)    {        return calcand(str);    }    for (int i = 0; i < cnt; i++)    {        if (calc(ors[i]))            return true;    }    return false;}int main(){    char str[1001];    int cnt = 0;    while (cin.getline(str, 1001))    {        cnt++;        string s = str;        if (calc(s))            cout << "Expression " << cnt << ": V" << endl;        else            cout << "Expression " << cnt << ": F" << endl;    }    return 0;}

3 后来F看了提到用树的思想,没有实现


4 最后来看一下神牛的方法:LL1文法——这尼玛才是编译原理活用到极致啊(swgr@poj)

#include<iostream>#include<string>using namespace std;string rep[14][2] = {" ","","!!","","(V)","V","(F)","F","!V","F","!F","V","V&V","V","V&F","F","F&V","F","F&F","F","V|V","V","V|F","V","F|V","V","F|F","F"};string s;int main(){int i,t,count=1;while(getline(cin,s)){while (1){for(i=0;i<14;i++)if((t=s.find(rep[i][0]))!=string::npos){s.erase(t,rep[i][0].length());s.insert(t,rep[i][1]);break;}if (i==14) break;}cout<<"Expression "<<count++<<": "<<s<<endl;}return 0;}