转自:http://blog.csdn.net/a477997/article/details/7369151
1 * 2 / ( ( 3 + 4 ) * ( – 5 + 6 ) )
这样一个式子,采用二叉树实现四则运算,需要使用递归的思想。总共分两步,第一步是建立二叉树,第二步是计算。
建立二叉树:
将式子存入一个char[] expresstion中,然后带入一个消除多余括号的函数TrimOutParenthes(消除括号,例如(1 * 2 / ( ( 3 + 4 ) * ( – 5+ 6 ) ))的最外层括号,主要用于消除分支节点中的括号,例如( 3 + 4 )),然后从右向左扫描每一个元素,找到最外层(括号外的)中最左边的符号,将该符号(例如式子中的*)作为父节点,将符号两边的式子作为子节点。如下:
*
1 2/ ( ( 3 + 4 ) * ( – 5 + 6 ) )
然后递归计算这两个子节点,也就是作为表达式再次代入。
2 / ( ( 3 + 4 ) * ( – 5 + 6 ) )的计算结果是:
/
2 (( 3 + 4 ) * ( – 5 + 6 ) )
于是目前的结果就是
*
1 /
2 ( 3 + 4 ) * ( – 5 + 6 )
以此类推,得到整棵二插运算树。
package com.zeph.calculator;
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+(3+4)+5+6").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;
}
}
}