中缀转后缀表达式

目录

一、需求

二、字符串扫描法

         思路分析

         图解

         代码实现

三、使用ArrayList优化


一、需求

        A:中缀表达式转后缀表达式
           例:1+((2+3)*4)-5

二、字符串扫描法

  • 思路分析

        A:定义两个栈,运算符栈S1和储存中间结果栈S2;
        B:从左至右依次扫描字符串,遇到数字就入栈S2;
        C:扫描到运算符
          a:栈S1为空的话,直接入栈;
          b:栈S1非空,则与S1栈顶元素比较优先级,若当前运算符
             优先级高,则入栈,否则弹出S1栈顶元素并入栈S2,继
             续比较优先级;
        D:扫描到左括号,直接入栈S1;
        E:扫描到右括号,将S1中的左括号上面的所有元素全部出栈,并
           压入栈S2,最后出栈左括号;
        F:表达式扫描完毕后,将S1中的元素弹出并压入栈S2;
        G:栈S2自栈底向栈顶的元素,即为后缀表达式;

  • 图解

 

  • 代码实现

package cn.itcast_04;

import java.util.Stack;

/*
 * 需求:中缀表达式转后缀表达式
 *   例:1+((2+3)*4)-5----输出:1 2 3 + 4 * + 5 -
 *
 * 分析:
 *    A:定义两个栈,运算符栈S1和储存中间结果栈S2;
 *    B:从左至右依次扫描字符串,遇到数字就入栈S2;
 *    C:扫描到运算符
 *      a:栈S1为空的话,直接入栈;
 *      b:栈S1非空,则与S1栈顶元素比较优先级,若当前运算符
 *        优先级高,则入栈,否则弹出S1栈顶元素并入栈S2,继
 *        续比较优先级;
 *    D:扫描到左括号,直接入栈S1;
 *    E:扫描到右括号,将S1中的左括号上面的所有元素全部出栈,并
 *      压入栈S2,最后出栈左括号;
 *    F:表达式扫描完毕后,将S1中的元素弹出并压入栈S2;
 *    G:栈S2自栈底向栈顶的元素,即为后缀表达式;
 */
public class MidToBack {
	public static void main(String[] args) {

		// 给出字符串
		String expression = "1+((2+3)*4)-5";

		// 定义运算符栈S1和栈S2
		Stack<String> s1 = new Stack<String>();
		Stack<String> s2 = new Stack<String>();

		// 用于保存多位数
		String keepNum = "";

		// 对字符串进行扫描
		for (int i = 0; i < expression.length(); i++) {
			String item = expression.substring(i, i + 1);
			if (isOper(item.charAt(0))) {
				if (s1.empty()) {
					s1.push(item);
				} else {
					while (!s1.empty() && priority(item.charAt(0)) <= priority(s1.peek().charAt(0))) {
						String temp = s1.pop();
						s2.push(temp);
					}
					s1.push(item);
				}
			} else if (item.equals("(")) {
				s1.push(item);
			} else if (item.equals(")")) {
				while (!s1.empty() && !s1.peek().equals("(")) {
					String temp = s1.pop();
					s2.push(temp);
				}
				s1.pop();// 左括号扔掉
			} else {
				// 是数字
				keepNum += item;
				if (i == expression.length() - 1) {
					s2.push(keepNum);
				} else {
					char ch = expression.substring(i + 1, i + 2).charAt(0);
					if (isOper(ch) || ch == ')') {
						s2.push(keepNum);
						keepNum = "";
					}
				}

			}
		}

		// 将S1中的元素弹出并压入S2
		while (!s1.empty()) {
			String temp = s1.pop();
			s2.push(temp);
		}

		System.out.println("s2" + s2);

		// 遍历栈S2存放到字符串中
		String backExpression = "";
		String[] chs = new String[s2.size()];
		int index = 0;
		while (!s2.isEmpty()) {
			chs[index++] = s2.pop();
		}

		// 遍历数组
		for (index = chs.length - 1; index >= 0; index--) {
			backExpression += chs[index];
			backExpression += " ";
		}

		// 去掉最后的空格
		System.out.println("后缀表达式为:" + backExpression.trim());
	}

	// 判断字符是否为运算符
	public static boolean isOper(int ch) {
		return ch == '+' || ch == '-' || ch == '*' || ch == '/';
	}

	// 自定义运算符优先级
	public static int priority(int ch) {
		if (ch == '+' || ch == '-') {
			return 0;
		} else if (ch == '*' || ch == '/') {
			return 1;
		} else {
			return -1;// 这里左括号为保证能够在堆栈里,优先级设为最低
		}
	}
}

三、使用ArrayList优化

package cn.itcast_04;

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

/*
 *需求:
 *   A:1+((2+3)*4)-5 ---->  1 2 3 + 4 * + 5 -
 * 
 *分析:
 *   A:扫描字符串不方便,故采用ArrayList来存放字符串;
 *   B:将ArrayList传递给一个方法,遍历ArrayList,配合栈完成计算 
 */
public class MidToBack2 {
	public static void main(String[] args) {
		// 定义给逆波兰表达式
		String expression = "1+((2+3)*4)-5";

		List<String> list = toMidList(expression);

		List<String> backExpression = midToBack(list);

		// 遍历list
		System.out.println(list);
		System.out.println(backExpression);

	}

	// 将中缀表达式转为对应的List
	public static List<String> toMidList(String expression) {
		List<String> ls = new ArrayList<String>();
		int i = 0;
		String keepNum;
		char c;
		do {
			if ((c = expression.charAt(i)) < 48 || (c = expression.charAt(i)) > 57) {
				ls.add("" + c);
				i++;
			} else {
				keepNum = "";
				while (i < expression.length() && (c = expression.charAt(i)) >= 48
						&& (c = expression.charAt(i)) <= 57) {
					keepNum += c;
					i++;
				}
				ls.add(keepNum);
			}
		} while (i < expression.length());

		return ls;
	}

	// 转换为ArrayList [1,2,3,+,4,*,+,5,-]
	public static List<String> midToBack(List<String> ls) {
		// 定义符号栈和储存结果的s2
		Stack<String> s1 = new Stack<String>();
		List<String> s2 = new ArrayList<String>();// 只管存储就好了

		// 遍历ls
		for (String item : ls) {
			// 数字则入s2
			if (item.matches("\\d+")) {
				s2.add(item);
			} else if (item.equals("(")) {
				s1.add(item);
			} else if (item.equals(")")) {
				while (!s1.peek().equals("(")) {
					s2.add(s1.pop());
				}
				s1.pop();
			} else {
				while (s1.size() != 0 && priority(s1.peek().charAt(0)) >= priority(item.charAt(0))) {
					s2.add(s1.pop());
				}
				s1.push(item);
			}
		}

		// 将s1剩余运算符加入s2
		while (s1.size() != 0) {
			s2.add(s1.pop());
		}

		return s2;
	}

	// 自定义运算符优先级
	public static int priority(int ch) {
		if (ch == '+' || ch == '-') {
			return 0;
		} else if (ch == '*' || ch == '/') {
			return 1;
		} else {
			return -1;// 这里左括号为保证能够在堆栈里,优先级设为最低
		}
	}

}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中缀后缀表达式是一种将数学表达式从中缀形式换为后缀形式的方法。下面我以一个简单的数学表达式"c"为例来说明中缀后缀的过程。 在中缀后缀的过程中,我们需要使用一个栈来辅助操作。具体的步骤如下: 1. 创建一个空栈和一个空字符串,分别用来存储运算符和后缀表达式。 2. 从左到右遍历中缀表达式。对于每个元素,进行如下操作: - 如果当前元素是操作数(即字母或数字),则直接将其添加到后缀表达式中。 - 如果当前元素是运算符,则进行如下操作: - 如果栈为空,或栈顶元素为左括号"(",则将当前运算符入栈。 - 如果当前运算符的优先级大于栈顶运算符的优先级,则将当前运算符入栈。 - 如果当前运算符的优先级小于或等于栈顶运算符的优先级,则将栈顶运算符出栈,并添加到后缀表达式中。重复此步骤,直到当前运算符的优先级大于栈顶运算符的优先级为止。最后,将当前运算符入栈。 - 如果当前元素是左括号"(",则将其入栈。 - 如果当前元素是右括号")",则将栈中的元素出栈,并添加到后缀表达式中,直到遇到左括号"("为止。此时,将左括号出栈。 3. 当中缀表达式遍历完毕后,将栈中剩余的运算符依次出栈,并添加到后缀表达式中。 最后,输出得到的后缀表达式即为"c"。 需要注意的是,中缀后缀的算法中还涉及到对运算符优先级的处理,不同运算符具有不同的优先级,根据具体的运算符优先级规则进行处理。同时,也需要考虑到括号的影响,所以在遍历过程中需要根据遇到的括号进行相应的处理操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值