构建一颗表达式树, 本质仍是一颗二叉树,可在叶子节点存放操作数, 双亲结点放运算符,一棵子树又可以看作另一叶子节点。 以类似于霍夫曼编码的方式将栈中的结点组织起来,为了简化操作,以空格分割的字符串作为一个Token,首先将中缀表达式转换为后缀表达式。 实现思路, 数字直接输出, 碰到右圆括号, 不断弹栈并直到找到匹配的左圆括号. 看到其他运算符, 弹栈至找到低优先级的运算符, 该过程要保留左圆括号. import java.util.HashMap; public class PostfixConversion { public static final Integer BUF_SIZE = 100; /* 低优先级运算符 */ public static final Integer LOW_PRI_OP = 1; /* 高优先级运算符 */ public static final Integer HIGH_PRI_OP = 2; /* 圆括号 */ public static final Integer PAREN = 3; /* 运算符对照表 */ public static HashMap<String, Integer> opTable = new HashMap<>(); static { opTable.put("+", LOW_PRI_OP); opTable.put("-", LOW_PRI_OP); opTable.put("*", HIGH_PRI_OP); opTable.put("/", HIGH_PRI_OP); opTable.put("(", PAREN); opTable.put(")", PAREN); } /* 泛型栈的简单实现 */ private static class Stack<T> { int top = 0; T[] buf; Stack() { buf = (T[])new Object[BUF_SIZE]; } public void push(T item) { if (item == null) return; buf[top++] = item; } public T pop() { return (T)((top > 0) ? buf[--top] : null); } } /** * 将中缀表达式转换为后缀表达式 * @param infix 以空格分割的中缀表达式 * @return 逆波兰表达式 */ static String convert(String infix) { String[] input = infix.split(" "); StringBuilder output = new StringBuilder(); String temp; Stack<String> opStack = new Stack<>(); // 运算符栈 for (String str: input) if ( opTable.containsKey(str) ) { // 如果是运算符,进行处理 Integer priority = opTable.get(str); // 获取当前运算符优先优先级 if (priority == PAREN && ")".equals(str)) { // 输出运算符栈中与对应圆括号之间所有运算符 while (!"(".equals(temp = opStack.pop())) output.append(temp).append(" "); } else { // 输出优先级比当前高或相等的运算符,并把当前运算符压入栈中 for (temp = opStack.pop(); temp != null && opTable.get(temp) != PAREN && opTable.get(temp) >= priority; temp = opStack.pop()) output.append(temp).append(" "); opStack.push(temp); opStack.push(str); } } else // 不是运算符直接输出 output.append(str).append(" "); // 取出运算符栈中所有运算符 while (( temp = opStack.pop()) != null) output.append(temp).append(" "); return output.toString(); } /* TODO private static class Node<T> {} static Node<String> expTree(String postfix) {} */ } 有了后缀表达式,剩下只要构建树就可以了,继续沿用上面的类 /* 简单的二叉树实现 */ private static class <T> { T element; Node<T> left; Node<T> right; Node(T theElement) { this(theElement, null, null); } Node(T theElement, Node<T> lt, Node<T> rt) { element = theElement; left = lt; right = rt; } } /** * 将后缀表达式转换为表达式树 * @param postfix 要转换的后缀表达式 */ static Node<String> expTree(String postfix) { String[] token = postfix.split(" "); Stack<Node<String>> nodeStack = new Stack<>(); //树的结点栈 for ( String str: token) { if (opTable.containsKey(str)) { Node<String> rightNode = nodeStack.pop(); Node<String> leftNode = nodeStack.pop(); Node<String> tmp = new Node<>(str, leftNode, rightNode); nodeStack.push(tmp); } else nodeStack.push(new Node<String>(str)); } return nodeStack.pop(); } private static <T> void print(Node<T> t, int indent) { if (t != null) { print(t.right, indent + 1); for (int i= 0; i < indent; i++) System.out.print(" "); System.out.println(t.element); print(t.left, indent + 1); } } public static void main(String[] args) { System.out.println("=== inorder: ==="); String infix = "( a + ( b * c ) ) + ( ( ( d * e ) - f ) * g )"; System.out.println(infix+"\n=== postoreder: ==="); String postfix = convert(infix); System.out.println(postfix+"\n=== 表达式树: ==="); Node<String> expTree = expTree(postfix); print(expTree, 0); } /* * output: * => === inorder: === * => ( a + ( b * c ) ) + ( ( ( d * e ) - f ) * g ) * => === postoreder: === * => a b c * + d e * f - g * + * => === 表达式树: === * => g * => * * => f * => - * => e * => * * => d * => + * => c * => * * => b * => + * => a * => */