package 数据结构; import java.util.Arrays; import java.util.Queue; import java.util.Stack; import java.util.concurrent.LinkedBlockingQueue; /** * @program: java_每天一题 * @description: 使用栈及队列实现中缀表达式转后缀表达式功能 * 思路:1.初始化一个栈存放运算符s1,初始化一个队列存放后缀表达式q1 * 2.从左自右扫描中缀表达式 * 3.遇到数字,放入队列q1中 * 4.遇到运算符,进行比较运算符优先级 * 4.1 如果s1为空或者遇到左括号“(”,直接入栈 * 4.2 如果运算符优先级比栈顶优先级高,直接入栈 * 4.3 如果运算符优先级比栈顶优先级低,或者相等,想将s1顶层运算符弹出放入q1,再次转到4.1与新的顶层运算符相比较 * 5.遇括号时,如果是左括号“(”,直接入栈.如果是右括号,则依次弹出s1栈顶运算符,放入q1中,直到遇到左括号为止,此时将一对括号抛弃 * 6 重复步骤2-5,直到表达式最右边 * 7 将q1顺序输出 得到后缀表达式(逆波兰表达式) * @author: czg * @create: 2020-05-16 11:15 */ public class j_栈_中缀转后缀_逆波兰 { public static void main(String[] args) { System.out.println(Arrays.toString(infixToArrarSuffix("1+((2+3)*4)-5"))); } /** * 中缀表达式转后缀表达式(返回字符串格式) * @param infix 中缀表达式 * @return */ public static String infixToStringSuffix(String infix){ Stack<String> s1=new Stack<>();//存放运算符 Queue<String> q1=new LinkedBlockingQueue<String>();//存放后缀表达式 int index=0;//循环中缀表达式下标 StringBuilder result=new StringBuilder();//结果 while (true){ //获得下标指定元素 String element=getOneElement(infix,index); //如果是运算符 if(isOperator(element)){ //s1.peek() 查看栈顶 if(s1.empty()||"(".equals(element)||"(".equals(s1.peek())){ //如果s1为空或者遇到左括号“(”,直接入栈 s1.push(element); }else if(")".equals(element)){ //如果是右括号,则依次弹出s1栈顶运算符,放入q1中,直到遇到左括号为止,此时将一对括号抛弃 while (!s1.peek().equals("(")){ q1.add(s1.pop()); } //丢弃左括号 s1.pop(); }else if(operaPriority(element)>operaPriority(s1.peek())){ //如果运算符优先级比栈顶优先级高,直接入栈 s1.push(element); }else if(operaPriority(element)<=operaPriority(s1.peek())){ //如果运算符优先级比栈顶优先级低,或者相等,想将s1顶层运算符弹出放入q1,再次转到4.1与新的顶层运算符相比较 while (operaPriority(element)<=operaPriority(s1.peek())){ q1.add(s1.pop()); if(s1.empty()){ s1.push(element); break; } } }else { throw new RuntimeException("存在未知运算符,无法计算"); } }else if(isInteger(element)){ //直接存入q1 q1.add(element); } index=index+element.length(); //当到达末尾时,结束循环 if(index>=infix.length()){ if(!s1.empty()){ q1.add(s1.pop()); } break; } } while (!q1.isEmpty()){ result.append(q1.poll()); } return result.toString(); } /** * 中缀表达式转后缀表达式(返回字符串数组格式) * @param infix 中缀表达式 * @return */ public static String[] infixToArrarSuffix(String infix){ Stack<String> s1=new Stack<>();//存放运算符 Queue<String> q1=new LinkedBlockingQueue<String>();//存放后缀表达式 int index=0;//循环中缀表达式下标 while (true){ //获得下标指定元素 String element=getOneElement(infix,index); //如果是运算符 if(isOperator(element)){ //s1.peek() 查看栈顶 if(s1.empty()||"(".equals(element)||"(".equals(s1.peek())){ //如果s1为空或者遇到左括号“(”,直接入栈 s1.push(element); }else if(")".equals(element)){ //如果是右括号,则依次弹出s1栈顶运算符,放入q1中,直到遇到左括号为止,此时将一对括号抛弃 while (!s1.peek().equals("(")){ q1.add(s1.pop()); } //丢弃左括号 s1.pop(); }else if(operaPriority(element)>operaPriority(s1.peek())){ //如果运算符优先级比栈顶优先级高,直接入栈 s1.push(element); }else if(operaPriority(element)<=operaPriority(s1.peek())){ //如果运算符优先级比栈顶优先级低,或者相等,想将s1顶层运算符弹出放入q1,再次转到4.1与新的顶层运算符相比较 while (operaPriority(element)<=operaPriority(s1.peek())){ q1.add(s1.pop()); if(s1.empty()){ s1.push(element); break; } } }else { throw new RuntimeException("存在未知运算符,无法计算"); } }else if(isInteger(element)){ //直接存入q1 q1.add(element); } index=index+element.length(); //当到达末尾时,结束循环 if(index>=infix.length()){ if(!s1.empty()){ q1.add(s1.pop()); } break; } } String[] result=new String[q1.size()];//结果 for (int i = 0; i < result.length; i++) { result[i]=q1.poll(); } return result; } //获得一个元素 public static String getOneElement(String experssion,int index){ int count=index; String data=""; while (true){ String temp=""; if(experssion.length()==count+1) { temp=experssion.substring(index); }else { temp=experssion.substring(index,count+1); } if(isOperator(temp)){ data=temp; break; } if(isInteger(temp)||temp.equals(".")){ data=temp; if(experssion.length()==count+1){ break; } count++; }else if(data.length()>0){ break; } } return data; } //判断字符串是否为数字 public static boolean isInteger(String str) { try { new Double(str); return true; }catch (Exception e){ return false; } } //判断是否是运算符 public static boolean isOperator(String str){ return "+-*/()".indexOf(str)>=0; } //设置字符优先级 public static int operaPriority(String opera){ int result=0; switch (opera){ case "+": case "-": break; case "*": case "/": result=1; break; default: throw new RuntimeException("运算符优先级无法解析"); } return result; } }