四则运算 栈实现 Java版

四则运算的栈实现重要的一点就是把中缀表达式转换为后缀表达式。转换规则如下:

1. 遇到数字直接输出

2. 左括号直接压栈

3. 右括号则将将栈中在左括号以上的所有运算符弹出

4. 若是运算符,判断是否优先级比栈顶元素小或相等,若是,则将在左括号前或优先级大于或等于待压栈元素的栈中元素出栈。若不是,则正常压栈,正常压栈过程中需判断是否负数  

5. 遍历中缀表达式结束后,将栈中还存在的所有元素进行出栈


下面的demo版本不支持负数和小数

package wz.ido.algorithm;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

public class StackCalculator {
	private static Map<String, Integer> priorityMap = new HashMap<>();
	//设置操作符优先级
	static {
		priorityMap.put("+", 10);
		priorityMap.put("-", 10);
		priorityMap.put("*", 20);
		priorityMap.put("/", 20);
		priorityMap.put("(", 100);
		priorityMap.put(")", 100);
	}

	public static void main(String[] args) {
		
		String express = "(20+3*(4 - 2) + 1)/3";
		int result = calculte(express);
		System.out.println(result);
	}
	
	private static int calculte(String express)  {
		
		//后缀表达式序列
		List suffixExp = getSuffixExp(express);
		System.out.println(express);
		System.out.println(suffixExp);
		//计算表达式结果
		Integer result = getResult(suffixExp);
		
		return result;
	}
	
	private static Integer getResult(List suffixExp) {
		Stack<Integer> numStack = new Stack<Integer>();
		
		for (Object element : suffixExp) {
			if (element instanceof Integer) {
				numStack.push((Integer)element);
			} else {
				Integer secondNum = numStack.pop();
				Integer firstNum = numStack.pop();
				String operator = (String)element;
				
				Integer temResult = simpleCalculte(operator, firstNum, secondNum);
				numStack.push(temResult);
			}
		}
		
		return numStack.pop();
	}


	private static Integer simpleCalculte(String operator, Integer firstNum, Integer secondNum) {
		Integer result = 0;
		switch (operator) {
		case "+":
			result = firstNum + secondNum;
			break;
		case "-":
			result = firstNum - secondNum;
			break;
		case "*":
			result = firstNum * secondNum;
			break;
		case "/":
			result = firstNum / secondNum;
			break;

		default:
			break;
		}
		return result;
	}

	private static List getSuffixExp(String express)  {
		Stack<String> operatorStack = new Stack<String>();
		
		//后缀表达式序列
		List rtn = new ArrayList();
		
		StringBuffer numStr = new StringBuffer();
		String temChar;
		for (int i = 0; i < express.length(); i++) {
			temChar = express.substring(i, i + 1);
			//数字 字符时
			if (isNum(temChar)) {
				numStr.append(temChar);
				continue;
			}
			//空字符时
			if (" ".equals(temChar)) {
				continue;
			}
			
			//操作符时
			if (numStr.length() > 0) {
				Integer num = Integer.parseInt(numStr.toString());
				//中缀转后缀规则:1. 遇到数字直接输出,
				rtn.add(num);
				
				//置为空
				numStr = new StringBuffer();
			}
			
			//中缀转后缀规则:2. 空栈直接将操作符压栈,
			if (operatorStack.isEmpty()) {
				operatorStack.push(temChar);
			} 
			//中缀转后缀规则:3. 右括号则将将栈中在左括号以上的所有运算符弹出
			else if (temChar.equals(")")) {
				while (!operatorStack.lastElement().equals("(")) {
					rtn.add(operatorStack.pop());
				}
				
				operatorStack.pop();
			} else {
				/**
				 * 中缀转后缀规则: 4. 左括号直接压栈(优先级实现)
				 *             5. 若是运算符,判断是否优先级比栈顶元素小或相等,若是,
				 *                则将在左括号前或优先级大于或等于待压栈元素的栈中元素出栈。
				 * 				     若不是,则正常压栈(暂未处理负数)
				 * 			   
				 */
				
				while (!operatorStack.isEmpty()) {
					String lastOperator = operatorStack.lastElement();
					int lastPriority = priorityMap.get(lastOperator);
					int currentPriotity = priorityMap.get(temChar);
					if (currentPriotity <= lastPriority && !"(".equals(lastOperator) ) {
						rtn.add(operatorStack.pop());
					} else {
						break;
					}
					
				}
				operatorStack.push(temChar);
			}
		}
		
		
		//处理最后一个字符是数字的情况
		if (numStr.length() > 0) {
			Integer num = Integer.parseInt(numStr.toString());
			rtn.add(num);
		}
		
		// 6.遍历中缀表达式结束后,将栈中还存在的所有元素进行出栈
		while (!operatorStack.isEmpty()) {
			rtn.add(operatorStack.pop());
		}
		return rtn;
	}
	
	private static boolean isNum(String temp) {      
        return temp.matches("[0-9]");      
    } 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值