IT公司面试题收集整理-数据结构有关复习-算术表达式求值算法(带括号递归运算)

IT公司面试题收集整理---数据结构相关复习---算术表达式求值算法(带括号递归运算)

首先声明,这仅仅是一个算法的雏形,实用率几乎为0。我只说这个思想。代码是用java写的,可以运行,但是表达式和中间值不能为负数【因为我用的java的字符串截取,如果使用C语言的话,在不带括号的情况中,就没有这个问题了,也可以为负数】,下面我写出我的想法,然后你就知道为什么不能为负数了。

第一:判断有没有括号,有的话,遇到一个右括号,那么就截取对应的左括号与右括号之间的字符串,还要让字符串加一个=。【因为没有括号的方法中限制的】

第二:如果现在只有加减乘除的话,比如说1+2*3+4+5-5=,就进入循环

第三:分为两个栈,遇到一个符号的时候,先放数字栈数据,然后比较符号栈的顶部,与即将放入栈的符号,进行比较。如果即将进栈的优先级比顶部的优先级低,那么

数字栈出两个,符号栈出一个,进行计算,结果放到数字栈,即将放入栈的符号现在也放入栈。

第四:遇到等号的话,全部出栈。栈为空的话,返回数字栈的第一个值。【即最终结果】


package 计算器;

public class Demo {
	public double number[] = new double[6];// 数字栈
	public char sign[] = new char[6];// 符号栈,*/=优先级大于+-优先级
	public int topNum = -1;// 头指针
	public int topSign = -1;// 头指针

	// 表达式求值,带括号算法,注意:表达式一定要正确,并且不能出现负数,因为这个算法用的是字符串截取
	public double evaluation(String string) throws Exception {// 参数代表正确的表达式
		double result = 0;
		// 如果式子中包含括号,截取括号匹配中的字符串
		if (string.contains("(") || string.contains(")")) {
			int temp = 0;
			for (int i = 0; i < string.length(); i++) {
				if (string.charAt(i) == '(') {// 碰到左括号,记录下来
					temp = i;
					continue;
				}
				if (string.charAt(i) == ')') {// 碰到右括号,进行递归,实际上相当于出栈
					string = string.substring(0, temp)
							+ evaluation(string.substring(temp + 1, i) + "=")// 加个等号继续递归
							+ string.substring(i + 1);
					System.out.println(string);
					i = -1;
					continue;
				}
			}
		}
		// 现在式子中只有加减乘除的话,进行栈的操作
		for (int i = 0; i < string.length(); i++) {
			switch (string.charAt(i)) {
			case '+':
			case '-':
			case '*':
			case '/':
			case '=':
				result = calculate(string, i, string.charAt(i));
				string = string.substring(i + 1);
				i = -1;
				break;
			default:
				break;
			}
		}
		return result;
	}

	private double calculate(String string, int sub, char signal) {
		double x = Double.parseDouble(string.substring(0, sub));
		number[++topNum] = x;// 数字进栈
		if (topSign == -1) {// 如果符号栈为空
			sign[++topSign] = signal;
			return number[topNum];
		}
		if (signal == '=') {// 计算数值
			while (topSign != -1) {
				if (sign[topSign] == '+') {
					number[topNum - 1] += number[topNum];
				} else if (sign[topSign] == '-') {
					number[topNum - 1] -= number[topNum];
				} else if (sign[topSign] == '*') {
					number[topNum - 1] *= number[topNum];
				} else if (sign[topSign] == '/') {
					number[topNum - 1] /= number[topNum];
				}
				topSign--;
				topNum--;// 退栈
			}
			return number[topNum];
		}
		if (comparePriority(signal, sign[topSign])) {
			// 退栈,并且将计算结果放入数字栈中
			if (sign[topSign] == '+') {
				number[topNum - 1] += number[topNum];
			} else if (sign[topSign] == '-') {
				number[topNum - 1] -= number[topNum];
			} else if (sign[topSign] == '*') {
				number[topNum - 1] *= number[topNum];
			} else if (sign[topSign] == '/') {
				number[topNum - 1] /= number[topNum];
			}
			sign[topSign] = signal;// 符号栈应该是topSign--【退栈】,然后++【进栈】,在这里我们直接换符号了
			topNum--;// 退栈
		} else {
			sign[++topSign] = signal;// 进栈
		}
		return number[topNum];
	}

	/**
	 * 比较a,b的优先级if(a<==b)那么返回true
	 */
	boolean comparePriority(char a, char top) {
		boolean judge = false;
		if ((a == '+' || a == '-')
				&& (top == '+' || top == '-' || top == '*' || top == '/')) {
			judge = true;
		}
		if ((a == '*' || a == '/') && (top == '*' || top == '/')) {
			judge = true;
		}
		return judge;
	}

	public static void main(String[] args) {
		try {
			System.out.println(new Demo().evaluation("1*(2+3/(5-2))+4+5="));
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("对不起,表达式不是标准的正数运算表达式,过程值也不能为负");
		}
	}
}
看到这里,你可能会觉得我这个局限比较大,确实是这样,这个确实比较水。因为还要考虑好多种情况,我只把这个算法的思想写了出来。真正要写好这个表达式求值的话,还真是不容易。

如果哪位大哥能给我一个不错的源码,我就感激不尽了。

还有就是,我听人说,这个带括号的,不用递归的话,可以用三个栈来进行操作,可能我智力有限吧,实在是想不出来怎么操作三个栈才能算出来,哪个大哥指点一下,我就不胜感激了。