Expression Tree的结构实现及面试题举例:计算字符串算术表达式的结果

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的精妙之处,望各位看官不吝指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值