利用二叉树计算四则运算表达式

先做个简单实现,没有括号,所有数字都是个位数


主要思路如下:

例如有这样一个四则运算表达式

2+3*4/2-3+1

先将其分成两部分的和:

2+3*4/2-3     +    1

+号作为二叉树的根,左右两部分分别作为二叉树根的左右子树

再依次递归的分下去。

最终将其转化为下面这样的一棵树:

二叉树




















计算时,使用二叉树的后续遍历,先算左子树的值,再算右子树的值,然后根据自己的操作符进行计算,再返回给上一层就行了。

实现代码如下:

public class Calculator {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Calculator ca=new Calculator();
		ca.calculator();
		
	}
	public void calculator()
	{
		int a=new TreeNode("9-2*2/1+2*2+5*6/3-2+4").calculate();
		System.out.print(a);
	}
	class TreeNode{
		char value;
		TreeNode left;
		TreeNode right;
		public TreeNode(String expression)
		{
			char[] exc = expression.toCharArray();
			
			int length = exc.length;
			int index=0;
			
			if(length>1)
			{
				for(int i=length-1;i>=0;i--)
				{
					if(exc[i]=='*'||exc[i]=='/')
					{
						index = i;
					}else
						if(exc[i]=='+'||exc[i]=='-')
					{
						index = i;
						break;
					}
				}
				StringBuilder sbleft = new StringBuilder();
				StringBuilder sbright = new StringBuilder();
				
				for(int i=0;i<index;i++)
				{
					sbleft.append(exc[i]);
				}
				for(int i=index+1;i<length;i++)
				{
					sbright.append(exc[i]);
				}
				left=new TreeNode(sbleft.toString());
				right= new TreeNode(sbright.toString());
			}
			value = exc[index];
		}
		
		public int calculate()
		{
			int result=0;
			if(left==null && right ==null)
			{
				result =Integer.parseInt(Character.toString(value));
			}else
			{
				int leftResult =left.calculate();
				int rightResult=right.calculate();
				switch(value){
				case '+': 
					result=leftResult + rightResult;
					break;
				case '-': 
					result=leftResult - rightResult;
					break;
				case '*': 
					result=leftResult * rightResult;
					break;
				case '/': 
					result=leftResult / rightResult;
					break;
				default: break;
				}
			}
			return result;
		}
	}
}

然后改进一下,表达式可以有括号,支持多位数和小数的运算。

代码如下:

public class Calculator {

	/**
	 * @param args
	 * @author JiangQifan
	 * @since 2012/3/19
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Calculator ca=new Calculator();
		ca.calculator();
		
	}
	public void calculator()
	{
		double a=new TreeNode("1+(-2.1)").calculate();
		System.out.println(a);


	}
	
	
	class TreeNode{
		
		double data;
		char operation;
		TreeNode left;
		TreeNode right;
		
		
		/*
		 * recursively construct the tree
		 */
		public TreeNode(String expression)
		{
			char[] exc = toCharArrayTrimOutParenthes(expression);
			if(exc == null)
			{
				return;
			}
			exc=syntaxCheck(exc);
			int length = exc.length;

			int index=0;
			
			if (hasOperation(exc)) {
				int parenthes = 0;
				
				for (int i = length - 1; i >= 0; i--) {
					
					
					if(exc[i] == '(')
					{
						parenthes --;
					}else if(exc[i] == ')')
					{
						parenthes++;
					}
					
					if (parenthes > 0) {
						continue;
					}
					
					if(exc[i] == '*' || exc[i] == '/')
					{
						index = i;
					}else if(exc[i] == '+' || exc[i] == '-')
					{
						index = i; 
						break;
					}
					
				}
				if(isOperation(exc[index]))
				{
					operation = exc[index];
				}
				StringBuilder sbleft = new StringBuilder();
				StringBuilder sbright = new StringBuilder();
				
				for(int i=0;i<index;i++)
				{
					sbleft.append(exc[i]);
				}
				for(int i=index+1;i<length;i++)
				{
					sbright.append(exc[i]);
				}
				left=new TreeNode(sbleft.toString());
				right= new TreeNode(sbright.toString());
				
				
			}
			else
			{
				StringBuilder value= new StringBuilder(); 
				value.append(exc);
				data = Double.parseDouble(value.toString());
			}
		}
		
		/*
		 * check the expression's syntax
		 * if there is two or more continuous operations,print out syntax error
		 * add '0' before the '-' if it's a negative
		 */
		public char[] syntaxCheck(char[] cArray)
		{
			boolean flag = false;
			if(isOperation(cArray[0]))
			{
				char [] checkedArray = new char[cArray.length+1];
				checkedArray[0] = '0';
				for(int i=0;i<cArray.length;i++)
				{
					checkedArray[i+1] = cArray[i];
				}
				cArray = checkedArray;
			}
			for(int i =0;i<cArray.length;i++)
			{
				if(isOperation(cArray[i]))
				{
					if(flag == true)
					{
						System.out.println("syntaxError");
					}
					flag = true;
				}else
				{
					flag = false;
				}
			}
			
			return cArray;
		}
		/* is there operations in the char array
		 *  if there is,return true.
		 *  if not,return false
		 */
		public boolean hasOperation(char[] cArray)
		{
			for(int i=0;i<cArray.length;i++)
			{
				if(isOperation(cArray[i]))
				{
					return true;
				}
					
			}
			return false;
		}
		public boolean isOperation(char c)
		{
			return (c == '+' || c == '-' || c== '*' || c == '/' );
		
		}
		
		/*
		 * trim the out most  useless parentheses
		 * and return a char array
		 */
		public char[] toCharArrayTrimOutParenthes(String src)
		{	
			
			if(src.length() == 0)
			{
				return null;
			}
			String result = src;
			while(result.charAt(0) == '(' && result.charAt(result.length()-1) == ')')
			{
				int parenthes = 0;
				for(int i = 0;i<result.length()-1;i++)
				{
					if(result.charAt(i) == '(')
					{
						parenthes++;
					}
					else if(result.charAt(i) == ')')
					{
						parenthes--;
					}
					if(parenthes==0)
					{
						return result.toCharArray();
					}
				}
				result = result.substring(1, result.length()-1);
				
			}
			
				return result.toCharArray();
		}
		
		//recursively calculate
		public double calculate()
		{
			double result=0;
			if(left==null && right ==null)
			{
				result =data;
			}else
			{
				double leftResult =left.calculate();
				double rightResult=right.calculate();
				switch(operation){
				case '+': 
					result=leftResult + rightResult;
					break;
				case '-': 
					result=leftResult - rightResult;
					break;
				case '*': 
					result=leftResult * rightResult;
					break;
				case '/': 
					result=leftResult / rightResult;
					break;
				default: break;
				}
			}
			return result;
		}
	}
}


  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值