zoukankan      html  css  js  c++  java
  • 波兰表示法(前缀表示法)

     

    波兰表示法, 也叫前缀表示法。

     

    运算波兰表达式时,无需记住运算的层次,只需要直接寻找第一个运算的操作符。以二元运算为例,从左至右读入表达式,遇到一个操作符后跟随两个操作数时,则计算之,然后将结果作为操作数替换这个操作符和两个操作数;重复此步骤,直至所有操作符处理完毕。因为在正确的前缀表达式中,操作数必然比操作符多一个,所以必然能找到一个操作符符合运算条件;而替换时,两个操作数和一个操作符替换为一个操作数,所以减少了各一个操作符和操作数,仍然可以迭代运算直至计算整个式子。多元运算也类似,遇到足够的操作数即产生运算,迭代直至完成。迭代结束的条件由表达式的正确性来保证。下面是一个例子,演示了每一步的运算顺序: 

    其特点是操作符置于操作数的前面,因此也称做前缀表示法。如果操作符的元数(arity)是固定的,则语法上不需要括号仍然能被无歧义地解析 

     

    计算方法:

     

    运算波兰表达式时,无需记住运算的层次,只需要直接寻找第一个运算的操作符。以二元运算为例,从左至右读入表达式,遇到一个操作符后跟随两个操作数时,则计算之,然后将结果作为操作数替换这个操作符和两个操作数;重复此步骤,直至所有操作符处理完毕。因为在正确的前缀表达式中,操作数必然比操作符多一个,所以必然能找到一个操作符符合运算条件;而替换时,两个操作数和一个操作符替换为一个操作数,所以减少了各一个操作符和操作数,仍然可以迭代运算直至计算整个式子。多元运算也类似,遇到足够的操作数即产生运算,迭代直至完成。迭代结束的条件由表达式的正确性来保证。下面是一个例子,演示了每一步的运算顺序:

    − × ÷ 15 − + 1 1 3 + 2 + 1 1 =

    − × ÷ 15 − 2     3 + 2 + 1 1 =

    − × ÷ 15 5         3 + 2 + 1 1 =

    − × 3              3 + 2 + 1 1 =

    − 9                  + 2 + 1 1 =

    − 9                  + 2 2     =

    − 9                  4         =

    5

    等价的中缀表达式:  ((15 ÷ (7 − (1 + 1))) × 3) − (2 + (1 + 1)) = 5

    下面的伪代码用一个stackprefix的值 。注意和上面的从左到右处理的算法不同,是从右往左扫描 , 但两个算法计算出来的值相同。(其实这个算法相当于后续遍历时候先遍历右子树)

    Scan the given prefix expression from right to left

    for each symbol

     {

      if operand then

        push onto stack

      if operator then

       {

        operand1=pop stack

        operand2=pop stack

        compute operand1 operator operand2

        push result onto stack

       }

     }

    return top of stack as result

     

    Applying this algorithm to the example above yields the following:

    − × ÷ 15 − 7 + 1 1 3 + 2 + 1 1 =

    − × ÷ 15 − 7 + 1 1 3 + 2 2     =

    − × ÷ 15 − + 1 1 3 4         =

    − × ÷ 15 − 2     3 4         =

    − × ÷ 15 5         3 4         =

    − × 3              3 4         =

    − 9                  4         =

    5

    This uses the same expression as before and the algorithm above.

    − × ÷ 15 − 7 + 1 1 3 + 2 + 1 1

     

    Token

    Action

    Stack

    Notes

    1

    Operand

    1

    Push onto stack.

    1

    Operand

    1 1

    Push onto stack.

    +

    Operator

    2

    Pop the two operands (1, 1), calculate (1 + 1 = 2) and push onto stack.

    2

    Operand

    2 2

    Push onto stack.

    +

    Operator

    4

    Pop the two operands (2, 2), calculate (2 + 2 = 4) and push onto stack.

    3

    Operand

    3 4

    Push onto stack.

    1

    Operand

    1 3 4

    Push onto stack.

    1

    Operand

    1 1 3 4

    Push onto stack.

    +

    Operator

    2 3 4

    Pop the two operands (1, 1), calculate (1 + 1 = 2) and push onto stack.

    7

    Operand

    7 2 3 4

    Push onto stack.

    Operator

    5 3 4

    Pop the two operands (7, 2), calculate (7 − 2 = 5) and push onto stack.

    15

    Operand

    15 5 3 4

    Push onto stack.

    ÷

    Operator

    3 3 4

    Pop the two operands (15, 5), calculate (15 ÷ 5 = 3) and push onto stack.

    ×

    Operator

    9 4

    Pop the two operands (3, 3), calculate (3 × 3 = 9) and push onto stack.

    Operator

    5

    Pop the two operands (9, 4), calculate (9 − 4 = 5) and push onto stack.

    The result is at the top of the stack.

     calc_prefix.cpp 代码实现如下 :

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<stack>
    using namespace std;
    bool is_op(char c)
    {
        return c=='+' || c=='-' || c=='*' || c=='/';
    }
    
    int calc(char op, int l, int r)
    {
        switch(op)
        {
            case '+':
                return l+r;
            case '-':
                return l-r;
            case '*':
                return l*r;
            case '/':
                return l/r;
        }
        return 0;
    }
    
    int calc_prefix(char* buf)
    {
        stack<int> st;
        int i=strlen(buf)-1;
        while(i>=0)
        {
            printf("%d
    ", i);
            if(is_op(buf[i]))
            {
                int l, r;
                l=st.top(); st.pop();
                r=st.top(); st.pop();
                st.push(calc(buf[i], l, r));
                --i;
            }
            else if(isdigit(buf[i]))
            {
                --i;
                while(isdigit(buf[i]))
                    --i;
                st.push(atoi(&buf[i+1]));
            }
            else
            {
                //white space
                --i;
            }
        }
        cout<<"stack size: "<<st.size()<<endl;
        return st.top();
    }
    
    int main()
    {
        char buf[256];
        while(gets(buf))
        {
            cout<<calc_prefix(buf)<<endl;
        }
    
        return 0;
    }
    

     输入:

    - * / 15 - 7 + 1 1 3 + 2 + 1 1

    输出:

    5

     

    参考:

    http://en.wikipedia.org/wiki/Polish_notation 及其中文链接

     

     

     

  • 相关阅读:
    【Flask项目】 python学习第一章
    【Oracle】整理oracle命令 转载
    C# 利用SQLite对.DB和.logdb加密和解密和SQLite创建数据库
    C# 利用ICSharpCode.SharpZipLib实现在线加密压缩和解密解压缩
    Django Cookie 和 Sessions 应用
    Django中添加富文本编辑器
    Django实现简单分页功能
    Xadmin集成富文本编辑器ueditor
    Django安装Xadmin步骤
    Pycharm小技巧--使用正则进行查找和批量替换
  • 原文地址:https://www.cnblogs.com/cute/p/3977058.html
Copyright © 2011-2022 走看看