Java 中缀表达式转换为后缀表达式

计算机进行运算并不是按照中缀表达式来进行运算的,而是按照后缀表达式。

如何将中缀表达式转换为前缀、后缀表达式。例如式子:1 + 2 * (9 - (6-4) *2 + 5),按照运算顺序将每一步都加上括号 (1 + (2 * (((9 - ((6-4) *2)) + 5)))),再将运算符号移到括号的前面和后面,+(1 *(2 +((-(9 *(-(64) 2))  5))))  ,(1 (2  (((9 ((6 4) - 2)*) -  5))+)*)+ , 再去掉括号就成了前缀表达式和后缀表示式,+1 *2 +-9 *-64 2  5   ,   1 2 9 6 4 - 2 * - 5 + * +。

算法描述

第一步:扫描字符串,去除空格。

第二步:遍历字符串,操作数直接入队列,

            运算符:“+ - * / ”

                     栈顶元素first与入栈运算符current作优先级比较,若priority(first) >= priority(current),则入栈,反之first出栈,加入队列

            左括号:" ( "

                    直接入栈

             右括号: " ) "

                     扫描栈,将栈里元素出栈,加入队列,直到扫描碰到左括号,并将左括号出栈。

第三步:遍历队列,操作数直接入栈,碰到运算符ch则将栈顶操作数n1,n2出栈,运算operate(n2,n1,ch),再将结果入栈,重复第三步。

代码实现


import java.util.ArrayList;
import java.util.List;

public class Main {
	public static void main(String[] args) {
		String s = "1 + 2 * (9 - (6-4) *2 + 5)";
		Calculator calc = new Calculator();
		Object[] exp = calc.compile(s);
		int result = calc.calculate(exp);
		System.out.println(s + " => " + expressionToString(exp) + " => " + result);
	}

	static String expressionToString(Object[] exp) {
		List<String> list = new ArrayList<>(exp.length);
		for (Object e : exp) {
			list.add(e.toString());
		}
		return String.join(" ", list);
	}

}

import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;

public class Calculator {

	public Object[] compile(String s) {
		Object[] parsed = parseAsExpression(s);
		List<Object> output = new LinkedList<>();
		Deque<Character> stack = new LinkedList<>();
		for (Object e : parsed) {
			if (e instanceof Integer) {
				output.add(e);
			} else {
				char ch = (Character) e;
				switch (ch) {
				case ')':
					// find '(' in stack:
					for (;;) {
						if (stack.isEmpty()) {
							throw new IllegalStateException("Compile error: " + s);
						}
						char top = stack.pop();
						if (top == '(') {
							break;
						} else {
							output.add(top);
						}
					}
					break;
				case '(':
					stack.push(ch);
					break;
				case '+':
				case '-':
				case '*':
				case '/':
					// find all operators that >= ch:
					while (!stack.isEmpty()) {
						char first = stack.peek();
						if (priority(first) >= priority(ch)) {
							stack.pop();
							output.add(first);
						} else {
							break;
						}
					}
					stack.push(ch);
					break;
				default:
					throw new IllegalStateException("Compile error: " + s);
				}
			}
		}
		while (!stack.isEmpty()) {
			output.add(stack.pop());
		}
		return output.toArray();
	}

	public int calculate(Object[] expression) {
		Deque<Integer> stack = new LinkedList<>();
		for (Object e : expression) {
			if (e instanceof Integer) {
				stack.push((Integer) e);
			} else {
				char op = (Character) e;
				int n1 = stack.pop();
				int n2 = stack.pop();
				int r = operate(op, n2, n1);
				stack.push(r);
			}
		}
		return stack.pop();
	}

	Object[] parseAsExpression(String s) {
		List<Object> list = new ArrayList<>();
		for (char ch : s.toCharArray()) {
			if (ch >= '0' && ch <= '9') {
				int n = Integer.parseInt(String.valueOf(ch));
				list.add(n);
			} else if ("+-*/()".indexOf(ch) != (-1)) {
				list.add(ch);
			} else if (ch == ' ') {
				// ignore white space
			} else {
				throw new IllegalArgumentException("Compile error: invalid char \'" + ch + "\'");
			}
		}
		return list.toArray();
	}

	// priority from high to low: '*', '/' > '+', '-' > '('
	int priority(char op) {
		switch (op) {
		case '*':
		case '/':
			return 2;
		case '+':
		case '-':
			return 1;
		case '(':
			return 0;
		default:
			throw new IllegalArgumentException("bad operator: " + op);
		}
	}

	int operate(char operator, int a, int b) {
		switch (operator) {
		case '+':
			return a + b;
		case '-':
			return a - b;
		case '*':
			return a * b;
		case '/':
			return a / b;
		default:
			throw new UnsupportedOperationException();
		}
	}

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值