逆波兰表达式——中缀转后缀Java代码实现
7.7 中缀表达式转后缀表达式
思路:
-
初始化 两个栈,运算符栈
s1和存储中间结果的栈s2 -
从左至右扫描中缀表达式
-
遇到操作数时直接压入
s2 -
遇到运算符时,比较其与
s1栈顶运算符的优先级-
如果
s1为空,或栈顶运算符为左括号"(",则直接将运算符压入s1 -
否则,若优先级比栈顶运算符的高,也将压入运算符
s1 -
否则,将
s1栈顶的运算符弹出并压入到s2中,再次转到(4 - 1)与s1中新的栈顶运算符相比较
-
-
遇到括号时:
-
如果是左括号"(",则直接压入
s1 -
如果是右括号")",则一次弹出
s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将着一对括号丢弃
-
-
重复2至5,直到表达式的最右边
-
将
s1中剩余的运算符依次弹出并压入s2 -
依次弹出
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 }

浙公网安备 33010602011771号