3、中缀表达式转换成后缀表达式

一、需求分析

1、给定一个中缀表达式"( 3 + 4 ) * 5 + 6";
2、将其转换为后缀表达式,并计算结果。

二、思路分析

1、需要使用两个栈,一个用于存放后缀表达式的中间结果(tempStack)和一个用于存放操作符(operStack);
2、扫描到"(",此时operStack为空,直接入栈
operStack => “(”
3、扫描到"3",数字直接入栈tempStack
tempStack => “3”
operStack => “(”
4、扫描到"+",优先级大于operStack栈顶元素的优先级,直接入栈operStack
tempStack => “3”
operStack => “(”,"+"
5、扫描到"4",数字直接入栈tempStack
tempStack => “3”,“4”
operStack => “(”,"+"
6、扫描到")",优先级最高,将operStack中元素依次弹出并入栈tempStack,遇见"(“停止
tempStack => “3”,“4”,”+"
operStack =>
7、扫描到"*",此时operStack为空,直接入栈
tempStack => “3”,“4”,"+"
operStack => “*”
8、扫描到"5",数字直接入栈tempStack
tempStack => “3”,“4”,"+",“5”
operStack => “*”
9、扫描到"+",其优先级低于operStack栈顶元素"*“的优先级且不是”(",将"*“弹出并压入到tempStack中,然后将”+“入栈operStack
tempStack => “3”,“4”,”+",“5”,"*"
operStack => “+”
10、扫描到"6",数字直接入栈tempStack
tempStack => “3”,“4”,"+",“5”,"*",“6”
operStack => “+”
11、扫描完毕,依次将operStack中元素弹出并入栈tempStack
tempStack => “3”,“4”,"+",“5”,"*",“6”,"+"
operStack =>
12、转换结束,此时将tempStack中元素依次弹出,其逆序就是后缀表达式

三、代码

package com.stack;

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

/**
 * 例如:(3+5)\*5-6对应的后缀表达式为3 5 + 5 \* 6 -,其求值步骤如下: 1.从左到右扫描,遇见数字直接入栈,3和5入栈;
 * 2.遇见操作符+,从栈中弹出两个数3和5,根据操作符计算结果为8,并将结果8入栈; 3.将5入栈;
 * 4.遇见操作符*,弹出两个操作符5和8,计算结果为5*8=40,将40入栈; 5.将6入栈;
 * 6.遇见操作符-,弹出两个数字6和40,计算结果为40-6=34,将34入栈; 7.字符串扫描完毕,栈中剩余数字34就是最终答案。
 * 
 * @author chaixf
 *
 */
public class PolandNotation {
	public static void main(String[] args) {
		// 中缀表达式(3+4)*5+6
		String midExpression = "3 + ( 3 + 4 ) * 6 / 3";
		String ress = midToSuffix(midExpression);
		System.out.println(midExpression + "的后缀表达式为:" + ress);
		System.out.println("后缀表达式的计算结果为:" + calculate(getListString(ress)));
	}

	/**
	 * 将字符串分割
	 * 
	 * @param suffixExpression
	 * @return 一个list
	 */
	public static List<String> getListString(String suffixExpression) {
		// 将suffixExpression进行分割
		String[] split = suffixExpression.split(" ");
		// 将split放进ArrayList中
		ArrayList<String> arrayList = new ArrayList<String>();
		for (String item : split) {
			arrayList.add(item);
		}
		return arrayList;
	}

	/**
	 * 计算后缀表达式的结果
	 * 
	 * @param list
	 * @return 一个整数结果
	 */
	public static int calculate(List<String> list) {
		// 创建一个栈
		Stack<Integer> stack = new Stack<Integer>();
		for (String item : list) {
			if (item.matches("\\d+")) {// 匹配到的是数字
				stack.push(Integer.parseInt(item));
			} else {// 匹配到的是操作符
					// 弹出两个数并计算结果
				int num2 = stack.pop();
				int num1 = stack.pop();
				int result = 0;
				switch (item) {
				case "+":
					result = num1 + num2;
					break;
				case "-":
					result = num1 - num2;
					break;
				case "*":
					result = num1 * num2;
					break;
				case "/":
					result = num1 / num2;
					break;
				default:
					throw new RuntimeException("操作符错误!");
				}
				// 将结果入栈
				stack.push(result);
			}
		}
		// 返回栈中的最后一个数据
		return stack.pop();
	}

	/**
	 * 将中缀表达式转换成后缀表达式
	 * 
	 * @param midExpression
	 * @return 后缀表达式
	 */
	public static String midToSuffix(String midExpression) {
		// 定义两个栈,一个用于存放中间表达式,一个用于存放操作符
		Stack<String> tempStack = new Stack<String>();// 用于存放中间表达式
		Stack<String> operStack = new Stack<String>();// 存放操作符
		// 扫描字符串
		List<String> list = getListString(midExpression);
		for (String item : list) {
			// 遇到数字直接进tempStack
			if (item.matches("\\d+")) {
				tempStack.push(item);
			} else {
				// 如果是操作符,就和operStack栈顶的元素比较优先级
				if (operStack.isEmpty()) {// 如果操作符栈为空,直接入栈
					operStack.push(item);
				} else {// 操作符栈不为空,就和栈顶操作符比较优先级
					if (priority(item) > priority(operStack.peek())) {// 当前操作符优先级大于栈顶优先级
						// 判断是不是右括号")"
						if (priority(item) == 4) {// 是右括号,则将operStack出栈并将出栈操作符入栈tempStack
							while (true) {
								String oper = operStack.pop();
								if (priority(oper) == 1) {// 遇见左括号,就停止出栈
									break;
								} else {// 不是左括号,就入栈tempStack
									tempStack.push(oper);
								}
							}
						} else {// 不是右括号,直接入栈operStack
							operStack.push(item);
						}
					} else {// 小于,等于栈顶优先级
						if(priority(item) == 1) { // 是左括号时,直接入栈
							operStack.push(item);
						}else { // 不是左括号,将栈顶操作符弹出并入栈tempStack
							tempStack.push(operStack.pop());
							operStack.push(item);
						}
					}
				}
			}
		}
		// 扫描完成后,将operStack中的操作符全部弹出到tempStack中
		while (!operStack.isEmpty()) {
			tempStack.push(operStack.pop());
		}
		// 扫描完成后,将tempStack中的字符全部弹出,其逆序就是后缀表达式
		String resString = "";
		while (!tempStack.isEmpty()) {
			resString += tempStack.pop();
		}
		return new StringBuffer(resString).reverse().toString().replace("", " ").trim();
	}

	public static int priority(String oper) {
		int res = 0;
		switch (oper) {
		case "(":
			res = 1;
			break;
		case "-":
			res = 2;
			break;

		case "+":
			res = 2;
			break;

		case "*":
			res = 3;
			break;

		case "/":
			res = 3;
			break;
		case ")":
			res = 4;
			break;

		default:
			throw new RuntimeException("操作符有误!");
		}
		return res;
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值