波兰表示法(前缀表示法)

 

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

 

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

其特点是操作符置于操作数的前面,因此也称做前缀表示法。如果操作符的元数(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\n", 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 及其中文链接

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 本题要求计算给定的波兰表达式的值,其中包含加、减、乘、除和幂运算。波兰表达式是一种前缀表达式,运算符位于操作数之前,例如 + 2 3 表示 2 + 3。波兰表达式的优点是不需要括号来改变运算次序,也不需要考虑运算符的优先级。因此,可以直接按照从左到右的顺序进行计算。 ### 回答2: 波兰表达式求值是一个经典的栈应用问题。算法流程如下: 1. 从左至右扫描表达式,遇到数字时把数字压入栈中; 2. 遇到运算符时,取出栈顶两个元素做相应运算,并把结果压入栈中; 3. 扫描完整个表达式后,栈中仅有一个数字,即为表达式的值。 具体实现中,需要注意以下几点: 1. 需要建立一个符号与对应二元运算的映射关系,可以使用哈希表或字典来实现; 2. 在处理幂运算时,需要注意幂底是第一个弹出的数字,幂指数是第二个弹出的数字,运算顺序需要反过来。 下面给出Python的实现代码(以空格分隔的波兰表达式存储在列表中): ```python operators = {'+': lambda x, y: x + y, '-': lambda x, y: x - y, '*': lambda x, y: x * y, '/': lambda x, y: x // y, '^': lambda x, y: y ** x} def eval_rpn(tokens): stack = [] for token in tokens: if token in operators: y, x = stack.pop(), stack.pop() stack.append(operators[token](x, y)) else: stack.append(int(token)) return stack[0] rpn = input().split() print(eval_rpn(rpn)) ``` 以上是对波兰表达式求值的解析和实现,希望能够对您有所帮助。 ### 回答3: 波兰表达式是一种把运算符前置的算术表达式,与我们常见的中缀表达式有所不同。波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,计算极为方便。 在计算波兰表达式中,需要先定义一个栈,从左至右依次遍历表达式的元素,如果是数字则直接入栈,如果是运算符,则出栈两个数,进行相应运算之后再将运算结果入栈。最后栈顶元素即为表达式的值。 根据题目要求,我们需要考虑五种运算符,分别为减法、乘法、除法、加法和幂运算。 1. 减法:减法在波兰表达式中比较简单,直接出栈两个数相减即可。 2. 乘法:乘法和除法操作相似,也是出栈两个数相乘再入栈。 3. 除法:除法需要注意被除数不能为0,如果出现了这种情况就应该报错。如果被除数不为0,则出栈两个数相除,再将结果入栈。 4. 加法:加法和减法类似,出栈两个数相加再入栈。 5. 幂运算:幂运算是指两个数相乘的结果作为底数,指数为另一个数的运算,因此需要先出栈两个数,并计算幂运算的结果,再将结果入栈。 综上所述,计算波兰表达式的过程其实就是遍历表达式的过程,如果是数字则入栈,如果是运算符则出栈计算后再入栈,最后的栈顶元素即为表达式的值。需要特别注意除数不能为0的情况。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值