逆波兰表达式

逆波兰表达式

逆波兰表达式又叫做后缀表达式

遵照下面的规则就可以转成逆波兰了:

1.首先把普通的表达式按照运算符分离出来放在一个集合E中,比如1+2*3 分离后集合里的元素就是 1 + 2 * 3 五个元素

2.再定义一个集合R(最好是字符串类型的集合,免得后面要转类型),主要是用来存放逆波兰表达式的,还有定义一个堆栈(存储运算符用),最后从左到右遍历集合E

3.遍历E的规则如下:

3.1如果该元素是数字,直接把它添加到集合R中

3.2否则它肯定是运算符,那么再进行判断

3.2.1如果该元素是左括号,或者当时栈为空,那么直接入栈

3.2.2如果该元素是右括号,则把栈内的运算符出栈并添加到集合R中,直到遇到第一个左括号结束(左括号也出栈但不添加到R)

3.2.3否则该元素是普通的运算符(也就是+-*/之类的),那么用该运算符和栈内的运算符号比较优先级,如果该运算符的优先级比栈内的运算符优先级高 或者 栈为空,则直接入栈,否则把栈内的运算符出栈并添加到R中,再判断下个栈内的运算符优先级,直到遇栈内的运算符优先级<=该运算符或者栈为空时再把该运算符入栈

3.3整个过程完成后,再把栈内的所有运算符出栈并添加到R中



下面看着表达式来理解上面的步骤

运算符优先级:

( ) 1

+ - 2

* / % 3

值越大优先级越高,注意括号优先级是最低的


表达式:2*(1+2/2)

定义集合E储存分离的表达式,E{ 2, *, (, 1, +, 2, /, 2, ) }

定义集合R储存逆波兰, R{...}

定义堆栈S储存运算符, S{...}

从左到右遍历E,开始判断

E[0]是数字2,直接添加到R,R{ 2 }

E[1]是乘号,和栈内运算符比较优先级,这时栈为空,所有直接入栈,S{*}

E[2]是左括号,直接入栈,S{ *, ( }

E[3]是数字1,直接添加到R,R{ 2, 1 }

E[4]是加号,比较栈顶运算符,栈顶为"(",加号比它优先级高,所有直接入栈, S{ *, (, + }

E[5]是数字2,直接添加到R, R{ 2, 1 , 2 }

E[6]是除号,比较栈顶运算符,栈顶为"+",除号>加号,直接入栈, S{ *, (, +, / }

E[7]是数字2,直接添加到R,R{2, 1, 2, 2}

E[8]是右括号,把栈内运算符出栈并添加到R直到遇到第一个左括号,R{ 2, 1, 2, 2, /, + } S{ * },注意左括号出栈但不加到R

那么整个过程就完毕,最后一步把栈内的所有元素添加到R

R{ 2, 1, 2, 2, /, +, * } S{...}

那么表达式2*(1+2/2) 转逆波兰变成 2 1 2 2 / + *


计算逆波兰非常简单,也需要一个堆栈,规则是:

1.从左到右遍历R

2.如果该元素是数字,直接入栈

3.如果该元素是运算符,出栈两个数,计算结果再入栈,逆波兰遍历完后栈内的元素就是表达式的值了

如:R{ 2, 1, 2, 2, /, +, * }

1.数字就入栈,那么S{ 2, 1, 2, 2 }

2.除号,出栈两个2 / 2 = 1,再入栈 S{ 2, 1, 1 }

3.加号,出栈两个1 + 1 = 2,再入栈S{ 2, 2 }

4.乘号,出栈两个2 * 2 = 4,再入栈S{ 4 }

5.逆波兰已遍历完,栈内元素是4,对照下普通表达式的运算结果是否相同?

你可能感兴趣的:(算法)