先做个简单实现,没有括号,所有数字都是个位数
主要思路如下:
例如有这样一个四则运算表达式
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;
}
}
}