栈的应用之中缀表达式转后缀表达式

1,中缀表达式的定义及为什么要将中缀表达式转换为后缀表达式?

中缀表达式(中缀记法)
中缀表达式是一种通用的算术或逻辑公式表示方法,操作符以中缀形式处于操作数的中间。中缀表达式是人们常用的算术表示方法。
虽然人的大脑很容易理解与分析中缀表达式,但对计算机来说中缀表达式却是很复杂的,因此计算表达式的值时,通常需要先将中缀表达式转换为前缀或后缀表达式,然后再进行求值。对计算机来说,计算前缀或后缀表达式的值要比中缀表达式简单。

比如,计算机计算后缀表达式的过程如下----后缀表达式的计算机求值:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次栈顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
例如后缀表达式“3 4 + 5 × 6 -”:
(1) 从左至右扫描,将3和4压入堆栈;
(2) 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈;
(3) 将5入栈;
(4) 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
(5) 将6入栈;
(6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。

2,中缀表达式转换为后缀表达式算法:

这里只用了一个栈来保存扫描中缀表达式时遇到的运算符。扫描过程中运算的操作数则直接 append 到输出表达式的末尾

?运算符在何种情况下压入栈?

若当前扫描的运算符的优先级大于栈顶运算符的优先级,则进行入栈。

若当前扫描的运算符的优先级与栈顶运算符的优先级相同,则需要判断当前扫描的运算符运算时的结合方向,若结合方向为从左至右,则不需要入栈;若结合方向为从右至左,则入栈。其中,加、减、乘、除 运算符的结合方向为从左至右,而求幂运算符的结合方向为从右至左。由于求幂运算符的最优级最高且它的结合方向为从右至左,故扫描遇到求幂运算符时直接将其入栈。

?对于中缀表达式中的括号的处理

左括号总是被压入栈。一旦左括号在栈中,就被当作优先级最低的运算符来对待,即:任何一个后继的运算符都将被压入栈。在遇到一个右括号时,从栈中弹出运算符并将它们添加到输出表达式末尾,直至弹出一个左括号为止(后缀表达式中没有括号,当然括号也就不需要添加到输出表达式了)。然后,算法再继续....

在从左向右处理中缀表达式的过程中,根据遇到的符号,执行下列动作:

①操作数         每个操作数都添加到输出表达式末尾(输出表达式就是最终得到的后缀表达式结果)

②运算符 ^(求幂运算)       ^ 压入栈(因为在所有的运算符中(加、减、乘、除、求幂)求幂运算的优先级最高,且求幂运算的结合方式为从右至左)

③运算符 + -  * /     从栈中弹出运算符,并将它们添加到输出表达式末尾,直至栈空或者栈顶优先级比新的运算符低,然后再将新的运算符压入栈

④左括号 (      压入栈

⑤右括号 )     从栈中弹出运算符,将它们添加到输出表达式末尾,直至弹出一个左括号,丢弃这两个括号

3,具体的中缀表达式转后缀表达式的JAVA代码实现

注意:程序中用来存放操作符的栈 不是 JDK 中java.util 包的Stack,而是自己实现的Stack。参考:使用JAVA数组实现顺序栈

 1 import list.SequenceStack;
 2 import list.Stack;
 3
 4 public class Postfix {
 5     /*
 6      * @Task: 将中缀表达式转换为后缀表达式
 7      * @param: infix 合法的中缀表达式字符串
 8      * @return: 与infix等价的后缀表达式字符串
 9      */
10     public static String convert2Postfix(String infix){
11         StringBuffer postfix = new StringBuffer();//初始化一个字符串缓冲区存放转换过程中生成的后缀表达式
12         Stack<Character> operatorStack = new SequenceStack<Character>();
13         int characterCount = infix.length();
14         char topCharactor;
15
16         for(int index = 0; index < characterCount; index++){
17             boolean done = false;
18             char nextCharacter = infix.charAt(index);
19             if(isVariable(nextCharacter))
20                 postfix = postfix.append(nextCharacter);
21             else{
22                 switch(nextCharacter)
23                 {
24                 case ‘^‘:
25                     operatorStack.push(nextCharacter);
26                     break;
27                 case ‘+‘: case ‘-‘: case ‘*‘: case ‘/‘:
28                     while(!done && !operatorStack.empty()){
29                         topCharactor = operatorStack.peek();
30                         if(getPrecedence(nextCharacter) <= getPrecedence(topCharactor)){
31                             postfix = postfix.append(topCharactor);
32                             operatorStack.pop();
33                         }
34                         else
35                             done = true;//当栈顶元素逐渐pop后,nextCharacter的优先级大于 栈顶的优先级
36                     }//end while
37                     operatorStack.push(nextCharacter);//当nextCharacter的优先级大于 栈顶的优先级,再把nextCharacter push 入栈
38                     break;
39                 case ‘(‘:
40                     operatorStack.push(nextCharacter);
41                     break;
42                 case ‘)‘:
43                     topCharactor = operatorStack.pop();
44                     while(topCharactor != ‘(‘){
45                         postfix = postfix.append(topCharactor);
46                         topCharactor = operatorStack.pop();
47                     }
48                     break;
49                 default:break;
50                 }//end switch
51             }
52         }//end for
53
54         while(!operatorStack.empty()){
55             topCharactor = operatorStack.pop();
56             postfix = postfix.append(topCharactor);
57         }
58         return postfix.toString();
59     }
60
61     private static int getPrecedence(char operator){
62         switch(operator)
63         {
64         case ‘(‘: case ‘)‘: return 0;//实际只有 + - * / 才需要调用该函数比较优先级
65         case ‘+‘: case ‘-‘: return 1;// + - 优先级为1
66         case ‘*‘: case ‘/‘: return 2;// * / 优先级为2
67         case ‘^‘:             return 3;
68         }
69         return -1;
70     }
71
72     //操作数默认用字母来表示
73     private static boolean isVariable(char charactor){
74         return Character.isLetter(charactor);
75     }
76
77     //for test purpose
78     public static void main(String[] args) {
79         String postfix = convert2Postfix("a/b*(c +(d-e))");
80         System.out.println(postfix);
81     }
82 }

参考资料:前缀、中缀、后缀表达式

算法详细解释参考《数据结构与算法JAVA语言描述第二版》--Frank M.Carrano 著.第21章

时间: 2024-12-24 15:43:13

栈的应用之中缀表达式转后缀表达式的相关文章

数据结构——栈——中缀表达式和后缀表达式

什么是中缀表达式,什么是后缀表达式 我们一般看见的多项式计算都是中缀表达式构成的:1+2*3+4/3 类似这种,为什么说是中缀呢?因为它的计算符号都是在两个数中间的. 那么自然而然的明白了后缀表达式是一种计算符号在两个数后面的. 如123*+43/+ 中缀表达式和后缀表达式有什么关系? 其实仔细你就会发现,上面给出的式子其实都是一样的,只是计算的顺序在后缀表达式中你看不懂而已. 因为我们习惯去看中缀表达式的计算. 其实他们之间是可以互相转换的.他们也可以表达同一个意思,同一个计算式子. 为什么会

将中缀表达式转换为后缀表达式,然后利用栈对表达式求值。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js.js"></script> </head> <body> 输入中缀表达式空格分隔 例如 2 + 3 <input type=

栈的应用:中缀表达式转为后缀表达式

1.中缀表达式转为后缀表达式 规则:(栈实现) 1)如果遇到操作数,我们就直接将其输出. 2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中. 3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止.注意,左括号只弹出并不输出. 4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止.弹出完这些元素后,才将遇到的操作符压入到栈中.有一点需要注意,只有在遇到" ) "的情况下

Python与数据结构[1] -&gt; 栈/Stack[1] -&gt; 中缀表达式与后缀表达式的转换和计算

中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操作数(数字/字母等),则加入后缀表达式中 若元素为操作符,则压入栈中,此时对比入栈操作符与栈内元素的计算等级,等级大于或等于入栈元素的栈内操作符都将被弹出栈,加入到后缀表达式中 左括号直接入栈,优先级最高,不弹出栈内元素 右括号不入栈,而是弹出所有元素加入后缀表达式,直至遇见匹配的左括号,并弹出左括

中缀表达式转为后缀表达式

** * 中缀表达式转后缀表达式 * * 作用:将一长串计算表达式转换为计算机易于操作的字符序列,用于计算器的设计 *  * 参与转换运算符 * +-/*()^% * * * 使用StringBuilder来保存转换出的后缀表达式 * 使用栈来操作运算符 * * * 转换原则 * 1.上述字符中()没有优先级值,+-优先级值为1,/*%优先级值为2,^优先级值为3 * 2.对于一个待计算的表达式,从左向右逐个检查每个字符 * 3.遇到数字,直接append到StringBuilder * 4.遇

ZH奶酪:Python 中缀表达式转换后缀表达式

实现一个可以处理加减乘数运算的中缀表达式转换后缀表达式的程序: 一个输入中缀表达式inOrder 一个输出池pool 一个缓存栈stack 从前至后逐字读取inOrder 首先看一下不包含括号的: (1)操作数:直接输出到pool (2)操作符:判断当前操作符与stack[top]操作符的优先级 <1>当前操作符优先级高于stack[top]:将当前操作符添加到stack中: <2>当前操作符优先级低于或等于stack[top]:从stack[top]开始出栈,直到stack[to

经典白话算法之中缀表达式和后缀表达式

一.后缀表达式求值 后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储. 假定待求值的后缀表达式为:6  5  2  3  + 8 * + 3  +  *,则其求值过程如下: (1)遍历表达式,遇到的数字首先放入栈中,依次读入6 5 2 3 此时栈如下所示: (2)接着读到"+",则从栈中弹出3和2,执行3+2,计算结果等于5,并将5压入到栈中. (3)然后读到8(数字入栈),将其直接放入栈中. (4)读到"*",弹出8和5,执行8*5,并将结果40压入栈中

[转]中缀表达式、前缀表达式、后缀表达式的相互转换

--------------------------------后缀转中缀---------------------------------------------- 1.建立一个栈,从左向右扫描后缀表达式,遇到运算数则压入栈: 2.遇到运算符就把栈顶两个元素出栈,执行运算,得到的结果作为新的运算符再压入栈: 3.依次走到表达式结尾: 例:把逆波兰式(即后缀表达式)ab+c*转换为中缀表达式: 1)a入栈(0位置) 2)b入栈(1位置) 3)遇到运算符"+",将a和b出栈,执行a+b的

数据结构中缀表达式转后缀表达式以及后缀转中缀表达式

最近一直在看数据结构这本书,我相信,对于每个程序员来说,数据结构都尤为重要.为什么要学,可以看看这位博友的认识http://blog.csdn.NET/sdkfjksf/article/details/54380659 直入主题:将中缀表达式转为后缀表达式 以及将后缀表达式转为前缀表达式的实现. 关于后缀转中缀,中缀转后缀的理论介绍,请先阅读其互转的理论知识,或者我转发的这篇文章,这里不再累赘,最好参考<数据结构与算法描述Java语言版>,接下来将会用java写. 一.首先,怎么实现中缀表达式