您的位置:首页 > 理论基础 > 数据结构算法

[数据结构]前缀、中缀、后缀表达式求值以及相互转换

2018-03-11 15:25 330 查看
前缀、中缀、后缀表达式求值以及相互转换

一、 表达式求值问题

1. 前缀表达式求值问题

从右向左扫描,遇到数字时,将数字压入栈,遇到运算符时候,把栈内前两个数字弹出,先弹出的数字放在运算符前面,然后进行相应运算,并将计算结果入栈。重复直到表达式最右端。

例:前缀表达式是:- 1 + 2 3(从右向左扫描)

a) 将数字3,2依次入栈;

b) 遇见运算符+,依次弹出2,3,计算2+3=5,将5入栈继续扫描;

c) 将1入栈;

d) 遇见运算符-,依次弹出1,5,计算1-5=-4,将-4入栈继续扫描;

e) 此时入栈到最左端,停止,所得结果-4

2. 中缀表达式求值问题

正常求值

3. 后缀表达式求值问题

从左向右扫描,遇到数字时,将数字压入栈,遇到运算符时候,把栈内前两个数字弹出,先弹出的数字放在运算符后面,然后进行相应运算,并将计算结果入栈。重复直到表达式最右端。

例:后缀表达式是34+5*6- (从左向右扫描)

a) 将数字3,4依次入栈;

b) 遇见运算符+,依次弹出4,3,计算3+4=7,将7入栈继续扫描;

c) 将5入栈;

d) 遇见运算符*,依次弹出5,7,计算7*5=35,将35入栈继续扫描;

e) 将6入栈;

f) 遇见运算符-,依次弹出两个6,35,计算35-6=29,将29入栈继续扫描;

g) 此时入栈到最右端,停止,所得结果29

二、 表达式相互转换问题

1. 前缀转化为其他类型表达式(构造树)

示例:* + 4 2 + 3 6

构造树: 1. 从左往右扫描字符串

2. 遇到操作符则递归构造树节点,当前操作符是根节点,并递归构造左右子节点

1) 前缀转化为中缀

中序遍历当前结果,中缀表达式为:(4+2)*(3+6)

2) 前缀转化为后缀

后序遍历当前结果,后续表达式为:4 2 + 3 6 + *

2. 中缀转化为其他类型表达式(栈或构造树)

方法一:栈

1)中缀转化为前缀

a) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;

b) 从右至左扫描中缀表达式;

c) 遇到操作数时,将其压入S2;

d) 遇到运算符时,比较其与S1栈顶运算符的优先级:

i. 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;

ii. 如果S1栈非空且当前运算符优先级比栈顶运算符的较高或相等,也将运算符压入S1;

iii. 如果S1栈非空但且当前运算符优先级比栈顶运算符的较低,将S1栈顶的运算符弹出并压入到S2中(当前运算符不放入S2栈),再次与S1中新的栈顶运算符相比较;

e) 遇到括号时:

i. 如果是右括号“)”,则直接压入S1;

ii. 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到一次右括号为止,此时
4000
将这一对括号丢弃;

f) 重复步骤(b)至(e),直到表达式的最左边;

g) 将S1中剩余的运算符依次弹出并压入S2;

h) 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。

2)中缀转化为后缀

1、初始化两个栈,运算符栈S1和数据栈S2

2、从左向右扫描中缀表达式,遇见数字直接入栈S2

3、遇见运算符,将比较运算符与S1栈顶运算符优先级

a) 如果S1栈顶是NULL或者是“(”则直接将遇见的运算符入栈S1

b) 如果S1栈顶非空也不是“(”,且遇见的运算符比S1内优先级要高,那么将遇见的运算符直接入栈S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况)

c) 如果S1栈顶是“)”或者遇到的运算符优先级更小。则将S1内运算符出栈到S2里,再转回a)

4、遇见括号

a) 如果是左括号“(”,则直接压入S1;

b) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;

5、重复2-4,直至到表达式最右边

6、将S1中剩余运算符弹出到S2

7、依次弹出S2中的元素并输出,结果的逆序即为所求后缀表达式(转换为前缀表达式时不用逆序)。

将中缀表达式exp转换为后缀表达式,采用了一个op运算符栈,其他的用数组存储。

方法二:构造树

首先将中缀表达式转换为表达式树,然后后序遍历表达式树,所得结果就是后缀表达式。

将中缀表达式转化为表达式树方法:表达式树的树叶是操作数,而其他的节点为操作符,根节点为优先级最低且靠右的操作符(如上述表达式优先级最低的是- 和+,但 + 更靠右,所以根为+),圆括号不包括。如上述中缀表达式转换后的表达式树如下:

经过前序遍历表达式树后得到的前缀表达式为:-+1*+2345

经过后序遍历表达式树后得到的后缀表达式为:123+4*+5–

后缀转化为其他类型表达式(构造树)

从左到右扫描后缀表达式,一次一个符号读入表达式。如果符号是操作数,那么就建立一个单节点树并将它推入栈中。如果符号是操作符,那么就从栈中弹出两个树T1和T2(T1先弹出)并形成一颗新的树,该树的根就是操作符,它的左、右儿子分别是T2和T1。然后将指向这棵新树的指针压入栈中。

前三个符号是操作数,因此创建三颗单节点树并将指向它们的指针压入栈中。

“+”被读入,因此指向最后两颗树的指针被弹出,形成一颗新树,并将指向新树的指针压入栈中。以下的流程图以相同原理执行。

1) 后缀转化为前缀

先序遍历所得的表达式树即得到我们所需的前缀表达式:-+1*+2345

2) 后缀转化为中缀

中序遍历所得的表达式树即得到我们所需的中缀表达式:1+((2+3)*4)-5
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: