逆波兰表达式实现表达式计算

一年多未更新博客了,此贴纯刷屏用。前段做培训留的题目,自己作了下,感觉蛮简单的代码测的时候还是有不少坑,只做了整数版本,懒得再弄了。

import java.util.ArrayList;
import java.util.Stack;

/**
 * 逆波兰表达式实现四则运算
 *
 * @author Duanhengbin
 *
 */
public class Exercise02 {

	// 四则运算式中的符号
	static String OPERATORS = "+-*/()";

	/**
	 * 根据输入的中缀表达式列表计算
	 * 
	 * @param aPstfix
	 * @return
	 */
	public static int RpnComputer(String expression) {
		Stack<String> stack = new Stack<String>();
		int num1, num2, result;
		num1 = num2 = result = 0;
		ArrayList<String> aPstfix = createPstfix(expression);
		for (String cell : aPstfix) {
			// 数字的场合
			if (OPERATORS.indexOf(cell) == -1) {
				stack.push(cell);
				// 符号的场合
			} else {
				// TODO: 支持带小数的数字计算
				num1 = Integer.parseInt(stack.pop());
				num2 = Integer.parseInt(stack.pop());
				switch (cell) {
				case "+":
					result = num2 + num1;
					break;
				case "-":
					result = num2 - num1;
					break;
				case "*":
					result = num2 * num1;
					break;
				case "/":
					result = num2 / num1;
					break;
				default:
					// TODO: throw Exception
				}
				stack.push(Integer.toString(result));
			}
		}
		return result;
	}

	/**
	 * 根据输入表达式字符串生成后缀表达式列表
	 * 
	 * @param s
	 * @return
	 */
	private static ArrayList<String> createPstfix(String s) {
		String[] cells = extractArrayFromExp(s);
		ArrayList<String> results = new ArrayList<String>();
		Stack<String> stack = new Stack<String>();
		for (String cell : cells) {

			if (OPERATORS.indexOf(cell) == -1) { // 数字的场合
				results.add(cell);

			} else { // 符号的场合
				if (cell.equals(")")) {
					// 待入栈“)”时,只出不入
					results.addAll(popStack(stack, cell));
				} else if (stack.isEmpty() || stack.peek().equals("(") || cell.equals("(") || "*/".contains(cell) && "+-".contains(stack.peek())) {
					// 这些为只入不出的情况
					stack.push(cell);
				} else {
					// 其他情况 先出后入
					if ("*/".contains(cell)) {
						results.add(stack.pop());
					} else {
						results.addAll(popStack(stack, cell));
					}
					stack.push(cell);
				}
			}
		}
		if (!stack.isEmpty()) {
			results.addAll(popStack(stack, ""));
		}
		return results;
	}

	/**
	 * 返回从当前栈中出栈且需要加入到表达式的符号列表
	 * 
	 * @param stack
	 * @return
	 */
	private static ArrayList<String> popStack(Stack<String> stack, String inSign) {
		ArrayList<String> rtn = new ArrayList<String>();
		// 将遇到“(”为止所有符号出栈
		while (!stack.isEmpty() && !"(".equals(stack.peek())) {
			rtn.add(stack.pop());
		}
		// 入栈“)”时,将“(”出栈
		if (inSign.equals(")")) {
			stack.pop();
		}
		return rtn;
	}

	/**
	 * 先将符号两侧增加空格,再替换多个空格为一个空格,最后用空格切分,将表达式拆分成数字与符号列表
	 * 
	 * @param s
	 * @return
	 */
	private static String[] extractArrayFromExp(String s) {
		String sOperator = null;
		// 在符号前后添加空格
		for (int i = 0; i < OPERATORS.length(); i++) {
			sOperator = OPERATORS.substring(i, i + 1);
			s = s.replaceAll("\\" + sOperator, " " + sOperator + " ");
		}
		// 将多个空白字符:[\t\n\x0B\f\r] 替换为一个空格 注意这里正则简记法\s
		s = s.replaceAll("[\\s]+", " ");
		return s.trim().split(" ");
	}
}

 测试代码

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collection;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import exercise.Exercise02;

@RunWith(Parameterized.class)
public class Exercise02Test {

	private String exep;
	private String result; 
	
	@Parameters 
	public static Collection<String[]> data()    { 
		return Arrays.asList(new String[][]   { 
			{ "9   +  	(3	-1)*  3+10/2 ", "20" },
			{ "((((2-3)*(8/2-1))))", "-3" },
			{ "((1+2+3) *  2)-10+4/2*3 ", "8" }, 
			{ "(1+2+3+4*5*6/2-9)", "57" },
			{ " (1*2*3*8-5*6/2/3/5-9)", "38" },
			{ " (1*2*3*6/9/2*10-(1+2)*4) ", "8" },
			{ "10-9/3+3*(2/(1/1))", "13" }
		}); 
	}	
	
	public Exercise02Test(String exep, String result)    { 
		this.exep = exep; 
		this.result = result; 
	} 
	
	@Test
	public void testRpnComputer() {
		assertEquals(result, String.valueOf(Exercise02.RpnComputer(exep)));
	}
}

 

你可能感兴趣的:(表达式)