逆波兰表达式——中缀转后缀Java代码实现

7.7 中缀表达式转后缀表达式

思路:

  1. 初始化 两个栈,运算符栈s1和存储中间结果的栈s2

  2. 从左至右扫描中缀表达式

  3. 遇到操作数时直接压入s2

  4. 遇到运算符时,比较其与s1栈顶运算符的优先级

    1. 如果s1为空,或栈顶运算符为左括号"(",则直接将运算符压入s1

    2. 否则,若优先级比栈顶运算符的高,也将压入运算符s1

    3. 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4 - 1)与s1中新的栈顶运算符相比较

  5. 遇到括号时:

    1. 如果是左括号"(",则直接压入s1

    2. 如果是右括号")",则一次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将着一对括号丢弃

  6. 重复2至5,直到表达式的最右边

  7. s1中剩余的运算符依次弹出并压入s2

  8. 依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

7.7.1 中缀表达式转换成后缀表达式代码实现

  1 import java.util.ArrayList;
  2 import java.util.List;
  3 import java.util.Stack;
  4   5 public class PolandNotation {
  6     public static void main(String[] args) {
  7         // 完成一个中缀表达式转换成后缀表达式
  8         // 说明
  9         // 1. 1+((2+3)*4)-5 => 1 2 3 + 4 * + 5 -
 10         // 2.因为直接对str进行操作,不方便,因此先将“1+((2+3)*4)-5” =>转成中缀表达式
 11         // 即“1+((2+3)*4)-5” => ArrayList[1,+,(,(,2,+,3,),*,4,),-,5]
 12         // 3. 将得到的中缀表达式对应的list转成后缀表达式对应的list
 13         // 即 ArrayList[1,+,(,(,2,+,3,),*,4,),-,5] =>  ArrayList[1, 2 ,3, +, 4, *, +, 5, -]
 14         String expression2 = "1+((2+3)*4)-5";
 15         List<String> infixExpressionList = toInfixExpressionList(expression2);
 16         System.out.println("中缀表达式对应List"+infixExpressionList);
 17  18         List<String> parseSuffixExpressionList = parseSuffixExpressionList(infixExpressionList);
 19         System.out.println("后缀表达式对应的list"+parseSuffixExpressionList);
 20  21         System.out.println(expression2+"结果是"+calculate(parseSuffixExpressionList));
 22        
 23     }
 24     
 25     // 方法: 将得到的中缀表达式对应的list 转换成 后缀表达式对应的list
 26     public static List<String> parseSuffixExpressionList(List<String> ls){
 27         // 定义两个栈
 28         Stack<String> s1 = new Stack<String>(); // 符号栈
 29         List<String> s2 = new ArrayList<String>(); // 存储中间结果的栈,因为该栈一直没有弹出过,所以使用List存储
 30  31         // 遍历ls
 32         for (String item: ls){
 33             // 如果是一个数就入栈,入栈s2
 34             if (item.matches("\\d+")){
 35                 s2.add(item);
 36             } else if (item.equals("(")){
 37                 // 如果是左括号就入栈,入栈s1
 38                 s1.push(item);
 39             } else if (item.equals(")")){
 40                 // 如果是右括号,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止
 41                 while (!s1.peek().equals("(")){
 42                     s2.add(s1.pop());
 43                 }
 44                 s1.pop(); // 将 ) 弹出s1栈,消除括号,小括号
 45             } else {
 46                 // 当 item 的优先级,小于或者等于栈顶运算符的优先级的时候,就应该将s1栈顶的运算夫弹出并压入s2中
 47                 while (s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)){
 48                     s2.add(s1.pop());
 49                 }
 50                 // 还需要将item压入栈
 51                 s1.push(item);
 52             }
 53         }
 54         // 将s1中剩余的元素压入s2
 55         while (s1.size() != 0){
 56             s2.add(s1.pop());
 57         }
 58         return  s2; // 因为是存放到List,因此按顺组输出就是对应的逆波兰表达式的List
 59     }
 60     // 方法:将中缀表达式转成对应的list
 61     public static List<String> toInfixExpressionList(String s){
 62         // 定义一个List,存放中缀表达式 对应的内容
 63         List<String> ls = new ArrayList<>();
 64         int i = 0; //  这个相当于一个指针,用于遍历中缀表达式字符串s
 65         String str = ""; // 用于对多位数的拼接工作
 66         char c; // 每遍历到一个字符就放到c
 67         do {
 68             // 如果c事一个非数字,我们就需要加入到ls中去
 69             if ((c=s.charAt(i))< 48 || (c=s.charAt(i)) > 57){
 70                 ls.add(""+c);
 71                 i++; // 需要后移
 72             } else {
 73                 // 如果是数字,需要考虑多位数的问题
 74                 str = ""; // 先将 str 置成空串
 75                 while (i < s.length() && ((c=s.charAt(i))>= 48 && (c=s.charAt(i)) <= 57)){
 76                     str += c; // 拼接
 77                     i++;
 78                 }
 79                 ls.add(str);
 80             }
 81         }while(i < s.length());
 82         return ls;
 83     }
 84     
 85     // 将一个逆波兰表达式,依次将数据和运算符 放入ArrayList
 86     public static List<String> getListString(String expression){
 87         // 将 expression 分割
 88         String[] split = expression.split(" ");
 89         List<String> list = new ArrayList<String>();
 90         for (String ele : split){
 91             list.add(ele);
 92         }
 93         return list;
 94     }
 95     
 96     
 97     // 完成对逆波兰表达式的运算
 98     /*
 99     1. 从左至右扫描,将 3 和 4 压入堆栈
100     2. 遇到 + 运算符,因此弹出 4 和 3 (4为栈顶元素,3 为次顶元素),计算出 3 + 4 的值,得 7, 再将 7 入栈
101     3. 将 5 入栈
102     4. 接下来是 X 运算符,因此弹出 5 和 7,计算出 7 X 5 = 35, 将 35 入栈
103     5. 将 6 入栈
104     6. 最后是 - 运算符,计算出 35 - 6(减法运算或者除法运算的时候,后缀表达式是 次顶元素  减去或除以  堆顶元素) 的值,即 29 ,由此得出最终结果
105      */
106 107     public static int calculate(List<String> ls){
108         // 创建一个栈,只需要一个栈即可
109         Stack<String> stack = new Stack<>();
110         // 遍历 ls
111         for(String item : ls){
112             // 这里使用一个正则表达式取出数
113             if (item.matches("\\d+")){
114                 // 匹配的是多位数
115                 stack.push(item);
116             } else {
117                 // pop 出两个数并运算,在入栈
118                 int num2 = Integer.parseInt(stack.pop());
119                 int num1 = Integer.parseInt(stack.pop());
120                 int res = 0;
121                 if (item.equals("+")){
122                     res = num1 + num2;
123                 } else if (item.equals("-")){
124                     res = num1 - num2;
125                 } else  if (item.equals("*")){
126                     res = num1 * num2;
127                 } else if (item.equals("/")){
128                     res = num1 / num2;
129                 } else {
130                     throw  new RuntimeException("符号有问题");
131                 }
132                 // 把res入栈,入栈的时候要将res转换成字符,因为我们的栈是字符串类型的
133                 stack.push(res+"");
134             }
135         }
136         // 最后留在stack的数据是运算结果
137         return Integer.parseInt(stack.pop());
138     }
139 }
140 141 142 // 编写一个类Operation 可以返回一个运算符 对应的优先级
143 class Operation{
144     private static  int ADD = 1;
145     private static  int SUB = 1;
146     private static  int MUL = 2;
147     private static  int DIV = 3;
148 149     // 写一个方法,返回对应的
150     public static int getValue(String operation){
151         int result = 0;
152         switch (operation){
153             case "+":
154                 result = ADD;
155                 break;
156             case "-":
157                 result = SUB;
158                 break;
159             case "*":
160                 result = MUL;
161                 break;
162             case "/":
163                 result = DIV;
164                 break;
165             default:
166                 System.out.println("不存在该数组");
167                 break;
168         }
169         return result;
170     }
171 }

 

 

 

posted @ 2021-08-03 09:59  笔锋  阅读(115)  评论(0)    收藏  举报