Expression Tree,专门用来处理运算式的一种数据结构。本篇讲到的是其中的一种:专门处理post-fix-order string的ExpressionTree。
但是,非常有必要说一声,当我们拥有了一个post-fix string形式的运算式字符串的时候,我们只要用一个Stack,就能轻松完成运算式的结果计算。
所以,要计算一个字符串算式表达式的最终结果,最大的难点并不是Expression Tree的结构如何实现,而是怎么样才能把一个正常order,即in-fix的字符串表达式,转换成post-fix的字符串表达式。那么为什么我这里要写一个Expression Tree呢?原因就是在今天之前,我不知道上面的那句话,天真的以为难点就是建立Expression树的过程。
不说废话,这里首先给出如何从in-fix到post-fix的算法和Java实现代码;之后是Expression Tree的实现和运算post-fix的代码;随后就是之前说到的只用一个Stack就能实现post-fix字符串运算的Java代码。
如何把in-fix字符串转换成post-fix字符串?利用一个Stack
1. 从左往右遍历in-fix的字符串
2. 遇到operand直接存到结果变量中
3. 遇到operator,压入栈中,但在此之前把栈里所有的比当前operator等级高的operator出栈,放到结果变量
4. 遇到左括号,压入栈中,直到遇到右括号,才把栈里所有左括号之前的operator放到结果变量,左括号出栈
用Java实现的转换代码:
public String toPostFix(String infix){
Stack<Character> st = new Stack<Character>();
StringBuilder sb = new StringBuilder();
for(int i=0; i<infix.length(); i++){
if(infix.charAt(i)==' ') continue;
else if(isOperand(infix.charAt(i))){
while(i<infix.length() && isOperand(infix.charAt(i))){
sb.append(infix.charAt(i)+"");
i++;
}
sb.append(" ");
i--;
}
else if(infix.charAt(i)=='('){
st.push('(');
}
else if(infix.charAt(i)==')'){
while(!st.isEmpty() && st.peek()!='('){
sb.append(st.pop()+" ");
}
st.pop(); //IMPORTANT: to pop out the '(' in stack
}
else if(infix.charAt(i)=='*' || infix.charAt(i)=='/'){
st.push(infix.charAt(i));
}
else if(infix.charAt(i)=='+' || infix.charAt(i)=='-'){
while(!st.isEmpty() && (st.peek()=='*' || st.peek()=='/')){
sb.append(st.pop() + " ");
}
st.push(infix.charAt(i));
}
// else continue;
}
while(!st.isEmpty()) sb.append(st.pop() + " ");
return sb.toString();
}
public boolean isOperand(char c){
if(c>='0' && c<='9') return true;
else return false;
}
Expression Tree的Java实现代码:
class Node{
Node left, right;
String val;
Node(String val){
this.val = val;
}
}
class ExpressionTree{
Node root;
ExpressionTree(){
root = null;
}
public void construct(String str){
Stack<Node> st = new Stack<Node>();
for(int i=0; i<str.length(); i++){
if(str.charAt(i)==' ') continue;
else if(isOperand(str.charAt(i))){
StringBuilder sb = new StringBuilder();
while(isOperand(str.charAt(i))){
sb.append(str.charAt(i)+"");
i++;
}
i--;
st.push(new Node(sb.toString()));
}
else{
Node x = new Node(str.charAt(i)+"");
x.right = st.pop();
x.left = st.pop();
st.push(x);
}
}
root = st.pop();
}
public int getResult(Node cur){
if(isOperand(cur.val.charAt(0))) return Integer.parseInt(cur.val);
else{
int left = getResult(cur.left);
int right = getResult(cur.right);
return compute(left, right, cur.val);
}
}
private int compute(int left, int right, String op){
if(op.equals("+")) return left + right;
else if(op.equals("-")) return left - right;
else if(op.equals("*")) return left * right;
else return left / right;
}
public boolean isOperand(char c){
if(c>='0' && c<='9') return true;
else return false;
}
}
只用一个Stack实现POST-FIX运算的Java代码:
public int getResult(String str){
Stack<Integer> st = new Stack<Integer>();
for(int i=0; i<str.length(); i++){
if(str.charAt(i)==' ') continue;
else if(isOperand(str.charAt(i))){
StringBuilder sb = new StringBuilder();
while(isOperand(str.charAt(i))){
sb.append(str.charAt(i)+"");
i++;
}
i--;
st.push(Integer.parseInt(sb.toString()));
}
else{
char c = str.charAt(i);
int right = st.pop();
int left = st.pop();
if(c == '+') st.push(left + right);
else if(c == '-') st.push(left - right);
else if(c == '*') st.push(left * right);
else st.push(left / right);
}
}
return st.pop();
}
小结:
最后再看的话,Expression Tree只是个巧妙地结构,相比单stack的方法,个人感觉没有任何优势可言。如有遗漏之处或者没想到的Expression Tree的精妙之处,望各位看官不吝指正。