中缀表达式转后缀表达式思路及实现
中缀表达式即人们平常所见的表达式,如我们数学里学的四则运算;
后缀表达式即计算机能正常识别的表达式;
以下是实现中缀转后缀的思路;
1、初始化两个栈,存放数据和数字
2、从左至右扫描表达式
3、遇到的是数字直接压入数字栈中
4、遇到符号时需分如下情况:
a、当该符号是第一个符号时直接压入
b、后续的符号需和栈顶的符号比较优先级,如果当前符号优先级高于栈顶符号,则直接压入,反之则将栈顶符号弹出压入数字栈,当前的符号压入符号栈
c、如符号是(则直接压入符号栈,如符号是)则需将符号栈中(之前的所有符号全部弹出压入数字栈中,最后弹出(并不存)符号;
5、最后如果符号栈中不为空,则全部弹出压入数字栈中
6、反向输出数字栈的元素即为后缀表达式
此处的数字栈可以用集合或字符串代替就不用反向输出了,直接正序输出即可。
代码方面做了一些简单的处理对于空格和数字有一些简单判断,但是还没有考虑到负数和中括号和大括号问题,其中中括号和大括号问题类似于小括号的处理思路,但是负数还需要特殊处理,暂时没有思考!!!
package com.arrayStack;
import io.micrometer.core.instrument.util.StringUtils;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class PostfixExpression {
/**
* 中缀表达式:人类正常看懂的表达式即为中缀表达式
* 后缀表达式:计算机看懂的表达式
* 中缀表达式转换后缀表达式
* a + b * c + ( d * e + f ) * g转换为后缀表达式
*/
private static String createPostfixExpression(String expression) {
StringBuilder postfixExpression = new StringBuilder();
Stack stack = new Stack();
//先对表达式做处理
String s = replaceAllBlank(expression);
String exp = addBlank(s);
String[] sp = exp.split(" ");
//遍历处理每个元素判断处理
for (String str:sp
) {
//判断是不是数字
boolean checkNo = checkNo(str);
if (checkNo){
//如果是数字直接放在返回结果的后缀表达式中
postfixExpression.append(str);
postfixExpression.append(",");
}else if ("+".equals(str)||"-".equals(str)||"*".equals(str)||"/".equals(str)||"(".equals(str)||")".equals(str)){
//如果栈内为空直接加入
if (stack.isEmpty()){
stack.push(str);
continue;
}
//如果是(符号也直接加入
if ("(".equals(str)){
stack.push(str);
continue;
}
if (")".equals(str)){
while (!stack.isEmpty()){
if ("(".equals(stack.peek())){
stack.pop();
break;
}
postfixExpression.append(stack.pop());
postfixExpression.append(",");
}
}else {
//判断当前符号和栈顶符号的优先级,如果大于则直接加入栈中,反之则取出栈顶符号输出到后缀表达式的返回结果中
while (true){
if (!stack.isEmpty()&&checkPriority(str)>checkPriority((String)stack.peek())){
stack.push(str);
break;
}else if (!stack.isEmpty()){
postfixExpression.append(stack.pop());
postfixExpression.append(",");
}else {
stack.push(str);
break;
}
}
}
}else {
//其他的符号暂时不考虑处理
throw new RuntimeException("输入的符号错误");
}
}//52-112=-60
//处理完每个元素后,如果栈中还有符号,则遍历出来追加在后缀表达式中
while (true){
if (stack.isEmpty()){
break;
}
postfixExpression.append(stack.pop());
postfixExpression.append(",");
}
return postfixExpression.toString().substring(0,postfixExpression.toString().length()-1);
}
//判断优先级如果是*或/返回1 +或—返回0值大者优先
private static int checkPriority(String str){
if ("*".equals(str)||"/".equals(str)){
return 1;
}else if ("+".equals(str)||"-".equals(str)){
return 0;
}else {
return -1;
}
}
//去除所有空格
public static String replaceAllBlank(String str) {
String s = "";
if (str != null) {
Pattern p = Pattern.compile("\\s*|\t|\r|\n");
/**
* \n 回车(\u000a)
* \t 水平制表符(\u0009)
* \s 空格(\u0008)
* \r 换行(\u000d)
*/
Matcher m = p.matcher(str);
s = m.replaceAll("");
}
return s;
}
//给中缀表达式的每个符号两边加一个空格,以便分割处理
private static String addBlank(String str){
if (StringUtils.isEmpty(str)){
return str;
}
if (str.contains("+")){
str = str.replace("+"," + ");
}
if (str.contains("-")){
str = str.replace("-"," - ");
}
if (str.contains("*")){
str = str.replace("*"," * ");
}
if (str.contains("/")){
str = str.replace("/"," / ");
}
if (str.contains("(")){
str = str.replace("("," ( ");
}
if (str.contains(")")){
str = str.replace(")"," ) ");
}
str = str.replace(" "," ").trim();
return str;
}
//判断是不是数字
private static boolean checkNo(String str){
String pre = "^[0-9]*[1-9][0-9]*$";
boolean b = Pattern.matches(pre, str);
return b;
}
public static void main(String[] args) {
String postfixExpression = createPostfixExpression("30 + 11 * 2 - ( 3 * 4 + 5 ) * 6");
System.out.println(postfixExpression);
}
}