缀是指操作符。
1. 前缀表达式(波兰式)
(1)不需用括号;
(2)不用考虑运算符的优先级;
(3)操作符置于操作数的前面。(如 + 3 2 )
1.1 中缀表达式转前缀表达式
1.1.1 加括号法/直接法
中缀表达式:a+b * c-(d+e)
第一步:按照运算符的优先级对所有的运算单位加括号
式子变成:((a+(b * c))-(d+e))
第二步:把运算符号移动到对应的括号前面
则变成:-( +(a * (bc)) +(de))
把括号去掉:-+a*bc+de 前缀式子出现
1.1.2 入栈法
C++:前缀、中缀、后缀表达式互相转换详解 ——小米内推官_AngelDg
遵循以下步骤:
- 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
- 从右至左扫描中缀表达式;
- 遇到操作数时,将其压入S2;
- 遇到运算符时,比较其与S1栈顶运算符的优先级:
4.1 如果S1为空,或栈顶运算符为右括号“)”,则直接将此运算符入栈;
4.2 否则,若优先级比栈顶运算符的较高或相等,也将运算符压入S1;
4.3 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较 - 遇到括号时:
5.1 如果是右括号“)”,则直接压入S1;
5.2 如果是左括号“(”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到右括号为止,此时将这一对括号丢弃 - 重复步骤(2)至(5),直到表达式的最左边;
- 将S1中剩余的运算符依次弹出并压入S2;
- 依次弹出S2中的元素并输出,结果即为中缀表达式对应的前缀表达式。
1.1.3 遍历树法
将中缀表达式写作表达式树,对其进行先前序遍历得到前缀表达式。
1.2 前缀表达式 逆向求解 中缀表达式
前缀/中缀/后缀----表达式之间的相互转换 —— DioDid
-+1*+2345
1.2.1 从左到右逐个比较
思路: 递归,碰到操作符就进入递归。
- 从右往左扫描先碰到+号,取+号后面两个操作数:2,3 得到:2+3.
- 继续往左扫碰到*号,取2+3和 4 得到:(2+3)*4
- 继续往左扫碰到+号,取1和(2+3)*4得到:1+(2+3)*4
- 继续往左扫碰到-号,取1+(2+3)*4和5得到:1+(2+3)*4-5
1.2.2 使用前缀表达式扫描推栈法
1.2 前缀表达式计算方式一
以二元运算为例,计算过程为:
(1)从左至右读入表达式;
(2)遇到一个操作符后跟随两个操作数时,则计算之;
(3)将结果作为操作数替换这个操作符和两个操作数;
(4)重复此步骤,直至所有操作符处理完毕。
因为在正确的前缀表达式中,操作数必然比操作符多一个,所以必然能找到一个操作符符合运算条件;
而替换时,两个操作数和一个操作符替换为一个操作数,所以减少了各一个操作符和操作数,仍然可以迭代运算直至计算整个式子。
多元运算也类似,从左至右,遇到足够的操作数即产生运算,迭代直至完成。
迭代结束的条件由表达式的正确性来保证。
1.3 前缀表达式计算方式二
(1)从右至左遍历表达式。
(2)遇到数字直接入栈。
(3)遇到运算符,取出两个数字,第一个作为操作数,第二作为被操作数,执行相应的运算。将运算的结果继续入栈。
(4)当表达式遍历完时,此时栈顶元素即为计算结果。
2. 后缀表达式(逆波兰式)
(1)不需用括号;
(2)无需考虑操作符的优先级;
(3)把操作数写在前面,把操作符写在后面。(如 3 2 +)
2.1 中缀表达式转后缀表达式
《数据结构》:中缀表达式转后缀表达式 + 后缀表达式的计算 —— Amentos
2.1.1 加括号法/直接法
中缀表达式 :a+b*c-(d+e)
第一步:按照运算符的优先级对所有的运算单位加括号~
式子变成:((a+(b * c))-(d+e))
第二步:把运算符号移动到对应的括号后面
则变成:((a(bc) * )- (de)+ )-
把括号去掉:a b c * - d e + - 后缀式子出现
2.1.2 入栈法
C++:前缀、中缀、后缀表达式互相转换详解 ——小米内推官_AngelDg
遵循以下步骤:
- 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
- 从左至右扫描中缀表达式;
- 遇到操作数时,将其压入S2;
- 遇到运算符时,比较其与S1栈顶运算符的优先级:
4.1 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
4.2 比栈顶高,也将运算符压入S1 (注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
4.3 比栈顶低或相同,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较; - 遇到括号时:
5.1 如果是左括号“(”,则直接压入S1;
5.2 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
可以想象成“(”比任何运算符都高,“)”比任何运算符都低。 - 重复步骤(2)至(5),直到表达式的最右边;
- 将S1中剩余的运算符依次弹出并压入S2;
- 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。
2.1.3 遍历树法
将中缀表达式写作表达式树,对其进行后序遍历得到后缀表达式。
2.2 后缀表达式 逆向求解 中缀表达式
1 2 3 + 4* 5 - +
2.2.1 从左到右逐个比较
基本思路和上面的一样: 递归,碰到操作符就进入递归
- 从左往右扫描先碰到+号,取+号前面两个操作数:2,3 得到:2+3.
- 继续往右扫碰到*号,取2+3 和 4 得到:(2+3)*4
- 继续往右扫碰到-号,取(2+3)*4和5得到:(2+3)*4-5
- 继续往右扫碰到+号:取(2+3)*4-5和1得到:1+(2+3)*4-5
2.2.2 使用后缀表达式扫描推栈法
2.3 后缀表达式计算方式
后缀(逆波兰)表达式的计算以及中缀转后缀的方法 —— 椰椰椰耶
按操作符从左到右出现的顺序依次执行(不考虑运算符之间的优先级)
这对于计算机而言是比较简单的结构。
(1)从左到右遍历表达式。
(2) 如果当前字符为变量或者为数字,则压栈;
(3)如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈。
(4)最后当表达式扫描完后,栈顶元素(也只会剩下一个元素)就是结果。
注意与前缀表达式(波兰式)第二种计算方式的相同点及共同点。
3. 中缀表达式
(1)操作符位于两个运算数中间。
(2)计算时要综合考虑操作符的优先级和括号。
如 5*(2+1) ,虽然 * 的优先级高于 + ,但括号的存在表示应优先执行括号内的 + 运算。
3.1 中缀表达式计算方式
《数据结构(C语言版)第二版》第三章-栈和队列(3.6)—— 3.6.3 表达式求值
《数据结构(C语言版)第二版》P79、P80
3.2 遍历树法获得中缀表达式
将中缀表达式写作表达式树,对其进行中序遍历,如有括号加上相应的括号,得到中缀表达式。
注意:
中序遍历可以用来表示一个表达式的结构,但它本身不包含足够的信息来完全确定运算符的优先级和结合性。
如果需要根据一个中序序列重建表达式树并正确地计算表达式,需要额外的括号信息来指导如何处理运算符。
如对表示表达式 a+b*(c-d)一e/f 的二叉树进行中序遍历,只能得到的中序序列为 a + b * c - d - e/f,显然与原表达式的计算顺序不同,要额外加括号规定运算顺序。