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

  • Post author:
  • Post category:其他


转自: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;
		}
	}
}