• 逆波兰表示法


    逆波兰表示法(Reverse Polish notation,RPN,或逆波兰记法),是一种是由波兰数学家扬·武卡谢维奇1920年引入的数学表达式方式,在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法。

    比如下列中缀表达式:

    (1-2)*(4+5)

    采用逆波兰表示法表示为:

    12-45+*

    逆波兰表示法中不需要圆括号,只要知道每个运算符需要几个操作数就不会引起歧义。

    中缀表达式转后缀表达式规则

    中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f  + g * +。

    转换过程需要用到栈,具体过程如下:

    1)如果遇到操作数,我们就直接将其输出。

    2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

    3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

    4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。也就是说这种操作," + "的优先级最低," ( "优先级最高。

    5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

    Program Source

    #include <iostream>
    #include <string.h>
    #include <stack>
    #include <stdlib.h>
    
    using namespace std;
    
    char symbol[] = "+-*/(";
    
    int getSymbol(char c)
    {
            int i;
            for(i=0; i<strlen(symbol); i++)
            {
                    if(symbol[i]== c)
                            break;
            }
            return i;
    }
    
    int getInt(char *p)
    {
            int i=0;
            while(isdigit(*p))
            {
                    i = i*10+(*p-'0');
                    p++;
            }
            return i;
    }
    
    int main(int argc, char* argv[])
    {
            char exp[]="1+2*3+(4*5+6)*7";
            char *p=exp;
    
            int t;
            stack<char> op;
    
            while(true)
            {
                    if(isdigit(*p))
                    {
                            t = getInt(p);
                            cout<<t<<endl;
                    }
    
                    if(*p==')')
                    {
                            while(op.top()!='(')
                            {
                                    cout<<op.top()<<endl;
                                    op.pop();
                            }
                            op.pop();
                    }
                    else if(*p=='(')
                    {
                            op.push('(');
                    }
                    else if(*p=='+'||*p=='-'||*p=='*'||*p=='/')
                    {
                            while(!op.empty()&&getSymbol(*p)<=getSymbol(op.top()))
                            {
                                    if(op.top()!='(')
                                    {
                                            cout<<op.top()<<endl;
                                            op.pop();
                                    }
                                    else
                                            break;
                            }
                            op.push(*p);
                    }
                    else if(*p=='')
                            break;
    
                    p++;
            }
    
            while(!op.empty())
            {
                    cout<<op.top()<<endl;
                    op.pop();
            }
    
            return 0;
    }

    前面提过的中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f  + g * +

    程序中的中缀表达式为1+2*3+(4*5+6)*7,其转换成后缀表达式则为123*+45*6+7*+

    验证结果

    [yangtze@localhost ~]$ g++ -o postfixExp postfixExp.cpp 
    [yangtze@localhost ~]$ ./postfixExp 
    1
    2
    3
    *
    +
    4
    5
    *
    6
    +
    7
    *
    +
    [yangtze@localhost ~]$ 
    
  • 相关阅读:
    做题记录
    关于有向图强连通分量的一点想法
    浅谈二分图匹配(未完)
    水题狂欢赛 (爬楼梯赛)题解(偏向自我反省)
    浅谈迭代加深(iddfs)
    浅谈单调队列优化
    [cqbzoj#10644]鱼肉炸弹题解
    树形背包[2/ 50] luogu [P1273]
    树形背包[1/ 50] luogu [P2015] (超级板)
    (树状数组)区间修改,区间查询
  • 原文地址:https://www.cnblogs.com/yangtze736-2013-3-6/p/3395522.html
Copyright © 2020-2023  润新知