逆波兰式(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)

https://github.com/KafuuNeko/CRPN

一.将一个普通的中缀表达式转换为逆波兰表达式

首先定义一个存储运算符的栈S,以及一个存放结果的字符串R

a.接着遍历普通中缀表达式的每个字符,定义当前玻璃到的字符名称为C
  若C是数字,则直接加入结果R
  若C为运算符,则判断该运算符类型
  1.若为右括号’)’,则不断弹出栈S中的符号输出至结果,直至遇到左括号
  2.若为左括号'(‘,则直接将此运算符加入到栈S
  3.若为数学运算符(+, -, , /, %)则判断运算符优先级
    最低优先级:左括号'(‘
    第二优先级:+ -
    第一优先级:
 / %
    接着获取栈S顶栈运算符的优先级,若顶栈运算符优先级大于或等于C运算符优先级,则弹出栈S顶栈运算符,加入至结果R,并重复此步骤,直至栈S顶栈运算符的优先级小于C运算符的优先级或栈S为空,接着将C运算符入栈S

b.处理完表达式字符串后,如果栈S内还有残留数据,那么依次出栈,加入到结果R

ExampleA:20 + 10 * 8

1[C:20]:数字直接加入结果
           R=[20], S=[]

2[C:+] :运算符+,则判断栈S顶栈运算符的优先级,因为此时栈S为空,所以直接加入到栈S
           运算符R=[20], S=[+]

3[C:10]:数字直接加入结果
           R=[20, 10], S=[+]

4[C:] :运算符,当前栈S顶栈运算符为+,优先级低于*,所以C直接加入到栈S
           R=[20, 10], S=[+, *]

5[C:8] :数字直接加入结果
           R=[20, 10, 8], S=[+, *]

处理完成,但此时栈不为空,则依次弹出栈内元素至结果

最终结果R=[20, 10, 8, *, +] 20 10 8 * +

ExampleB:10 + 5 * (20 - 5 - 10) + 8 - 10 / 2
   1[C:10] :数字直接加入结果
           R=[10], S=[]

2[C:+]  :运算符+,则判断栈S顶栈运算符的优先级,因为此时栈S为空,所以直接加入到栈S
           运算符R=[10], S=[+]

3[C:5]  :数字直接加入结果
           R=[10, 5], S=[+]

4[C:]  :运算符,当前栈S顶栈运算符为+,优先级低于*,所以C直接加入到栈S
           R=[10, 5], S=[+, *]

5[C:(]  :左括号,直接将此运算符加入到栈S
           R=[10, 5], S=[+, *, (]

6[C:20] :数字直接加入结果
           R=[10, 5, 20], S=[+, *, (]

7[C:-]  :运算符-,栈S顶栈为左括号'(',因为左括号优先级小于-,所以C直接加入栈S
           R=[10, 5, 20], S=[+, *, (, -]

8[C:5]  :数字直接加入结果
           R=[10, 5, 20, 5], S=[+, *, (, -]

9[C:-]  :运算符-,栈S顶栈运算符与C运算符优先级相同,弹出栈S顶栈内容至R后栈S顶栈为左括号'(',优先级小于运算符C,所以C再此时入栈S
           R=[10, 5, 20, 5, -], S=[+, *, (, -]

10[C:10]:数字直接加入结果
           R=[10, 5, 20, 5, -, 10], S=[+, *, (, -]

11[C:)] :右括号')',不断弹出栈S中的符号输出至结果,直至遇到左括号
           R=[10, 5, 20, 5, -, 10, -], S=[+, *]

12[C:+] :运算符+,弹出栈S内所有优先级大于或等于运算符+的符号至结果R后将C入栈
           R=[10, 5, 20, 5, -, 10, -, *, +], S=[+]

13[C:8] :数字直接加入结果
           R=[10, 5, 20, 5, -, 10, -, *, +, 8], S=[+]

14[C:-] :运算符-,弹出栈S内所有优先级大于或等于运算符+的符号至结果R后将C入栈
           R=[10, 5, 20, 5, -, 10, -, *, +, 8, +], S=[-]

15[C:10] :数字直接加入结果
           R=[10, 5, 20, 5, -, 10, -, *, +, 8, +, 10], S=[-]

16[C:/] :运算符/,此时栈S顶栈运算符‘-’的优先级小于‘/’,所以C直接加入栈S
           R=[10, 5, 20, 5, -, 10, -, *, +, 8, +, 10], S=[-, /]

17[C:2] :数字直接加入结果
           R=[10, 5, 20, 5, -, 10, -, *, +, 8, +, 10, 2], S=[-, /]

处理完成,但此时栈不为空,则依次弹出栈内元素至结果
   R=[10, 5, 20, 5, -, 10, -, *, +, 8, +, 10, 2, /, -]
   最终结果:10 5 20 5 - 10 - * + 8 + 10 2 / -

二.计算逆波兰表达式
计算方式十分简单,我们先定义一个存放数字的栈S
接着遍历逆波兰表达式,遇到数字则加入数字栈,遇到运算符则弹出两个数字栈顶栈数字,并使用此运算符对这两个数字进行计算,并将计算结果加入到数字栈内

ExampleA:20 10 8 * +
    1[C:20] :C加入到栈S
            S=[20]

2[C:10] :C加入到栈S
            S=[20, 10]

3[C:8] :C加入到栈S
            S=[20, 10, 8]

4[C:*] :取出栈S顶栈两个元素 N1:8, N2:10
            使用此运算符计算结果:R:N1 * N2 = 80,并将结果重新入栈
            S=[20, 80]

5[C:+] :取出栈S顶栈两个元素 N1:20, N2:80
            使用此运算符计算结果:R:N1 + N2 = 100,并将结果重新入栈
            S=[100]

当完成这些步骤后,栈S内剩下的最后一个元素即为表达式的计算结果,如果最后栈内元素不唯一,或在遍历到运算符时栈内元素数量少于2个,则都判定为此表达式有误