数据结构007_中缀转后缀表达式
中缀表达式转后缀表达式思路:
1.初始化两个栈:运算符栈S1和储存中间结果的栈S2;
2.从左到右扫描中缀表达式
3.遇到操作数时,将其压入S2;
4.遇到运算符,比较其与S1栈顶运算符的优先级:
- 如果S1为空,或栈顶运算符是左括号 '(' ,则直接将此运算符入栈;
- 若优先级比栈顶运算符的高,也将运算符压入S1;
- 若优先级没有S1栈顶优先级高,将S1栈顶的运算符弹出并压入S2中,再次与S1中新的栈顶运算符进行比较。
5.遇到括号时:
- 如果是左括号 '(' ,直接入栈S1;
- 如果是右括号,依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号,此时将这一对括号丢弃;
6.重复不准走2-5,直到表达式最右边
7.将S1中剩余的运算符依次弹出并压入S2;
8.依次弹出S2中元素并输出,结果的逆序即为中缀表达式对应的后缀表达式。
代码:
package com.njcx.test3; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class ToPolandExp { /** * 完成将中缀表达式转后缀表达式的功能 因为直接对string进行操作不方便, 因此先将"1+((20+3)*4)-5" 放入中缀表达式对应的list * 即arrayList[1,+,(,(,20,+,3,),*,4,),-,5,] */ public static void main(String[] args) { String expression = "1+((2+3)*4)-5"; List<String> list = toInfixExpressionList(expression); System.out.println("转换后的中缀表达式:" + list); List<String> ls = parseSuffixExpressionList(list); System.out.println("转换后的后缀表达式:" + ls); } /** * 将中缀表达式转成对应的list */ public static List<String> toInfixExpressionList(String s) { // 定义一个list存放中缀表达式对应的内容 List<String> list = new ArrayList<String>(); int i = 0; // 这是一个指针,用于遍历中缀表达式字符串 String str;// 做对多位数的拼接工作 char c;// 每遍历一个字符就放入ch中 do { // 如果ch是一个非数字,就需要加入到list中 48(0) 57(9) if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) { list.add("" + c); i++;// i 要后移 } else { // 如果是一个数需要考虑多位数 str = ""; // 先将str置成空串 while (i < s.length() && ((c = s.charAt(i)) >= 48 && (c = s.charAt(i)) <= 57)) { str += c;// 拼接 i++; } list.add(str); } } while (i < s.length()); return list; } /** * 将中缀表达式转换成后缀表达式 * * @param ls * 存放中缀表达式的列表,也是由上面的方法转换来哒 * @return */ public static List<String> parseSuffixExpressionList(List<String> ls) { // 注意哦,这里s2不用另一个栈了(因为s2全程也没有pop操作而且后续需要逆序,比较麻烦), // 直接用list作为s2,后面输出就是逆波兰表达式,不需要倒序 Stack<String> s1 = new Stack<String>();// 运算符栈 List<String> s2 = new ArrayList<String>(); // 存放中间结果的列表 for (String item : ls) { if (item.matches("\\d+")) { // 如果是一个数字,加入s2 s2.add(item); } else { // 如果是符号就多了,),(,+-*/ if (item.equals("(")) s1.push(item); else if (item.equals(")")) { while (!s1.peek().equals("(")) { // 这里怎么会报错啊,按道理有右括号一定有左括号啊 // 如果s1栈顶运算符不是"(",就要一直把运算符pop出来放进s2里 s2.add(s1.pop()); } s1.pop();// 这是丢掉"(",至此这对括号消除了 } else { // 如果是加减乘除就要和s1栈顶运算符比较优先级了,这里再编写一个类Operation可以返回运算符对应的优先级 if (s1.size() != 0 && Operation.getValue(item) < Operation.getValue(s1.peek())) s2.add(s1.pop()); s1.push(item); } } } // 判断完了,将s1中剩下的运算符弹出,依次进入s2 while (s1.size() != 0) s2.add(s1.pop()); return s2;// 注意因为是存放到List, 因此按顺序输出就是对应的后缀表达式对应的List } } /** * 编写一个类可以返回运算符对应的优先级 * * @author 抱金子 * */ class Operation { private static int add = 1; private static int sub = 1; private static int mul = 2; private static int div = 2; public static int getValue(String operation) { int val = 0; switch (operation) { case "+": val = add; break; case "-": val = sub; break; case "*": val = mul; break; case "/": val = div; break; default: break; } return val; } }
浙公网安备 33010602011771号