后序表达式 算术运算符在尾部,例如: 1 + 2
的后序形式:1 2 +
,后序表达式是没有括号的,所以转换的结果它是有操作符优先级的,例如:2 + 3 * 4
,它的后序表达式为:2 3 4 * +
,这个题如果假设所有的表达式都包括括号的话,如((1+2)*(4-3))
,它转换为后序表达式:1 2 + 4 3 - *
,我们还是valStack
保存数字,opStack
保存算术运算符。
遍历表达式,对于+
,-
,*
, /
,压入opStack
,对于数字
或(
压入valStack
,而碰到)
,取出两个数字,一个运算符,组合成字符串,压入栈:
for (int i = 0; i < chars.length; i++) { if (chars[i] == '+' || chars[i] == '-' || chars[i] == '*' || chars[i] == '/') { opStack.push(String.valueOf(chars[i])); } else if (chars[i] == ')') { String op = opStack.pop(); String val2 = valStack.pop(); String val1 = valStack.pop(); String val0 = valStack.pop(); String s = val1 + " " + val2 + " " + op; System.out.println("入栈字符串:" + s); valStack.push(s); } else { valStack.push(String.valueOf(chars[i])); } }
那么现在valStack
上都是每个括号组成的子表达式,我们依次出栈,拼装成字符串,就是我们要的结果:
while (!valStack.isEmpty()) { listStr = valStack.pop() + listStr; } System.out.println(listStr);
完整源码:
static void test1() { LinkStack<String> valStack = new LinkStack<>(); LinkStack<String> opStack = new LinkStack<>(); String listStr = ""; String str = "((1+2)*((3-4)*(5-6)))"; str = "((1+2)*(4-3))"; char[] chars = str.toCharArray(); for (int i = 0; i < chars.length; i++) { if (chars[i] == '+' || chars[i] == '-' || chars[i] == '*' || chars[i] == '/') { opStack.push(String.valueOf(chars[i])); } else if (chars[i] == ')') { String op = opStack.pop(); String val2 = valStack.pop(); String val1 = valStack.pop(); String val0 = valStack.pop(); String s = val1 + " " + val2 + " " + op; System.out.println("入栈字符串:" + s); valStack.push(s); } else { valStack.push(String.valueOf(chars[i])); } } while (!valStack.isEmpty()) { listStr = valStack.pop() + listStr; } System.out.println(listStr); }
它可以有括号,也可以没有,例如:(1+2)*(3-4)
,它的1 2 + 3 4 - *
:
加入括号,比较麻烦也比较困难,所以循序渐进,我们先处理没有括号的情况,1 + 2 * 4
,按照转换规则,应该先计算 2 * 4
,然后1 + 这个结果,将数字存到valStack
,运算符存到opStack
,当运算符要入栈前,如果当前运算符比栈顶的优先级低,则对opStack
出栈,对valStack
出栈两个数字,将这些数字组合成子运算,重新入栈,并对当前运算符入栈:
for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (c == '+' || c == '-') { if (!opStack.isEmpty()) { String v2 = valStack.pop(); String v1 = valStack.pop(); String op = opStack.pop(); String s = v1 + " " + v2 + " " + op; valStack.push(s); opStack.push(String.valueOf(chars[i])); } else { opStack.push(String.valueOf(chars[i])); } } else if (c == '*' || c == '/') { if (!opStack.isEmpty()) { String topOp = opStack.peek(); if (topOp.equals("+") || topOp.equals("-")) { opStack.push(String.valueOf(chars[i])); } else { String v2 = valStack.pop(); String v1 = valStack.pop(); String op = opStack.pop(); String s = v1 + " " + v2 + " " + op; valStack.push(s); opStack.push(String.valueOf(chars[i])); } } else { opStack.push(String.valueOf(chars[i])); } } else { valStack.push(String.valueOf(chars[i])); } //System.out.println(""); }
这样opStack
有一个运算符,对其出栈,然后对valStack
出栈两个数字,直到opStack
为空:
while (!opStack.isEmpty()) { String op = opStack.pop(); String val2 = valStack.pop(); String val1 = valStack.pop(); String s = val1 + " " + val2 + " " + op; valStack.push(s); //System.out.println("输出s: " + s); } System.out.println("str: " + str + " , 后序表达式为:" + valStack.peek());
valStack
栈顶就是最终的字符串:
根据我的一番思索,在前述没有括号的情况下扩展,(
可以看做是优先级最低的的算术操作符,)
是优先级最高的操作符,当前算术运算符低于栈顶的话,就进行出栈。两个括号都存到opStack
栈上,对于+
、-
,判断栈是否为空,栈顶如果是(
,表示当前是一个括号中的表达式,所以不能出栈,如果不是的话,进行出栈再入栈。
for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (c == '(') { opStack.push(String.valueOf(chars[i])); } else if (c == '+' || c == '-') { if (!opStack.isEmpty()) { String topOp = opStack.peek(); if (!topOp.equals("(")) { String v2 = valStack.pop(); String v1 = valStack.pop(); String op = opStack.pop(); String s = v1 + " " + v2 + " " + op; valStack.push(s); } opStack.push(String.valueOf(chars[i])); } else { opStack.push(String.valueOf(chars[i])); } } else if (c == '*' || c == '/') { if (!opStack.isEmpty()) { String topOp = opStack.peek(); if (topOp.equals("+") || topOp.equals("-")) { opStack.push(String.valueOf(chars[i])); } else { String v2 = valStack.pop(); String v1 = valStack.pop(); String op = opStack.pop(); String s = v1 + " " + v2 + " " + op; valStack.push(s); opStack.push(String.valueOf(chars[i])); } } else { opStack.push(String.valueOf(chars[i])); } } else if (c == ')') { String v2 = valStack.pop(); String v1 = valStack.pop(); String op2 = opStack.pop(); String op1 = opStack.pop(); String s = v1 + " " + v2 + " " + op2; valStack.push(s); } else { valStack.push(String.valueOf(chars[i])); } }
然后对opStack
出栈,同时对valStack
出栈2次,待opStack
出栈完毕后,栈顶就是最终的表达式。
while (!opStack.isEmpty()) { String op = opStack.pop(); String val2 = valStack.pop(); String val1 = valStack.pop(); String s = val1 + " " + val2 + " " + op; valStack.push(s); } System.out.println("str: " + str + " , 后序表达式为:" + valStack.peek());
全部源码:
static void test3() { LinkStack<String> valStack = new LinkStack<>(); LinkStack<String> opStack = new LinkStack<>(); String str = "((1+2)*((3-4)*(5-6)))"; str = "(1+2+3)*(3-4)+5"; char[] chars = str.toCharArray(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (c == '(') { opStack.push(String.valueOf(chars[i])); } else if (c == '+' || c == '-') { if (!opStack.isEmpty()) { String topOp = opStack.peek(); if (!topOp.equals("(")) { String v2 = valStack.pop(); String v1 = valStack.pop(); String op = opStack.pop(); String s = v1 + " " + v2 + " " + op; valStack.push(s); } opStack.push(String.valueOf(chars[i])); } else { opStack.push(String.valueOf(chars[i])); } } else if (c == '*' || c == '/') { if (!opStack.isEmpty()) { String topOp = opStack.peek(); if (topOp.equals("+") || topOp.equals("-")) { opStack.push(String.valueOf(chars[i])); } else { String v2 = valStack.pop(); String v1 = valStack.pop(); String op = opStack.pop(); String s = v1 + " " + v2 + " " + op; valStack.push(s); opStack.push(String.valueOf(chars[i])); } } else { opStack.push(String.valueOf(chars[i])); } } else if (c == ')') { String v2 = valStack.pop(); String v1 = valStack.pop(); String op2 = opStack.pop(); String op1 = opStack.pop(); String s = v1 + " " + v2 + " " + op2; valStack.push(s); } else { valStack.push(String.valueOf(chars[i])); } } while (!opStack.isEmpty()) { String op = opStack.pop(); String val2 = valStack.pop(); String val1 = valStack.pop(); String s = val1 + " " + val2 + " " + op; valStack.push(s); } System.out.println("str: " + str + " , 后序表达式为:" + valStack.peek()); }
输出信息:
str: (1+2+3)*(3-4)+5 , 后序表达式为:1 2 + 3 + 3 4 - * 5 +