数据结构-栈-栈的应用(使用逆波兰表达式《后缀表达式》实现简易版运算器)
数据结构-栈-栈的应用(使用逆波兰表达式《后缀表达式》实现简易版运算器)
运算器可以包含小数、小括号、加减乘除
package com.orz.Stack; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Stack; /** * @author orz * @create 2020-10-27 10:45 */ public class InfixExpressionSuffixExpressionTest{ public static void main(String[] args) { String str="12.8+(2 -3.55)*4+ 10/5.0"; double resultByString = InfixExpressionSuffixExpression.getResultByString(str); System.out.println(resultByString); } } class InfixExpressionSuffixExpression { public static List<String> getExpression(String infixExpression) { //索引,用于获取字符,从零到length-1 int index=0; //用于获取字符串中索引值为index的字符 char ch=' '; //用于返回数组list集合,保存运算符和数值 List<String> list=new ArrayList<>(); //循环遍历 while (index!=infixExpression.length()) { //获取字符串中索引值为index的字符 ch = infixExpression.charAt(index); //判断字符的优先级,-1代表非运算符非数值;0代表运算值, // 1代表+,-运算符;2代表*,x,X,/运算符;代表(,)小括号 int order = getCharOrder(ch); //如果是非运算符,非数值,直接跳过 if(order==-1) { index++; } else { //数值 //需要判断是否是多位数 if(order==0) { //用于拼接多位数 StringBuilder str = new StringBuilder(); //先把这个数值拼上,再判断下一个是否也是数值,如果是就接着拼接,并使index索引值下移 //直到找到下一个不是数值为止 str.append(ch); //索引值如果是length-1,说明已经是最后一个了,不需要再判断下一个是否是数值了,因为没有了 if(index!=infixExpression.length()-1) { int next = getCharOrder(infixExpression.charAt(index+1)); //判断下一个是否也是数值 //只要下一个字符也是数值类型,就拼接上;并使index+1 while (next == 0) { //下一个是 char c = infixExpression.charAt(index+1); str.append(c); index++; //判断是否到了最后一个,如果是最后一个,直接跳出循环体 if(index==infixExpression.length()-1) { break; } //没有到最后一个,在接着判断下一个是否还是数值型 next = getCharOrder(infixExpression.charAt(index+1)); } } //最后把多位数或者单位数加入到list中 list.add(String.valueOf(str)); index++; } else { //运算符,直接加入 list.add(String.valueOf(ch)); index++; } } } return list; } /** * 中缀表达式转后缀表达式 * ①设置一个空栈 * ②从左到右读取中缀表达式,当读取到一个操作数时,立即将它放到输出中 * ③当读取到运算符时,需要将该运算符放与当前栈顶元素比较,如果该运算符优先级·大于栈顶运算符的优先级,则将该运算符放入栈中; * 否则,将栈中的元素弹出直到栈顶元素低于该运算符的优先级; * ④如果读到的运算符是左括号时,将体压入栈中;如果读到的运算符是右括号时,将栈中的元素弹出直到遇到相对的左括号为止 * ⑤重复上面的步骤,直到处理完所有的字符 * @param list * @return */ public static List<String> getSuffixExpression(List<String> list) { List<String> arrayList=new ArrayList<>(list); List<String> suffixList=new ArrayList<>(); Stack<String> stack=new Stack<>(); for (String str:arrayList) { if(getCharOrder(str.charAt(0))==0) { suffixList.add(str); } else if(str.charAt(0)=='(') { stack.push(String.valueOf('(')); } else if(str.charAt(0)==')') { String popString = stack.pop(); while (popString.charAt(0)!='(') { suffixList.add(popString); popString=stack.pop(); } } else { if(stack.size()==0||stack.peek().charAt(0)=='(') { stack.push(str); } else{ int charOrder = getCharOrder(str.charAt(0)); String popString=stack.peek(); int charOrder1 = getCharOrder(popString.charAt(0)); while (charOrder<=charOrder1&&popString.charAt(0)!='('&&stack.size()>0) { suffixList.add(popString); stack.pop(); if(stack.size()==0) { break; } popString=stack.peek(); charOrder1 = getCharOrder(popString.charAt(0)); } stack.push(str); } } } while (stack.size()!=0) { suffixList.add(stack.pop()); } return suffixList; } /** * 使用后缀表达式计算 * 从左到右扫描,如果是数值,放入栈中,如果是操作符,则从栈中弹出两个操作数进行运算 * @param list * @return */ public static double getResult(List<String> list) { ArrayList<String> arrayList=new ArrayList<>(list); Stack<String> stack=new Stack<>(); for (String str:arrayList) { if(getCharOrder(str.charAt(0))==0) { stack.push(str); }else { char oper=str.charAt(0); double oper1=Double.parseDouble(stack.pop()); double oper2=Double.parseDouble(stack.pop()); double result=0; switch (oper) { case '+': result=oper2+oper1; stack.push(String.valueOf(result)); break; case '-': result=oper2-+oper1; stack.push(String.valueOf(result)); break; case '*': result=oper2*oper1; stack.push(String.valueOf(result)); break; case '/': //一定是最底的数除以上面的数 result=oper2/oper1; stack.push(String.valueOf(result)); break; default: break; } } } return Double.parseDouble(stack.pop()); } /** * 判断字符的优先级,-1代表非运算符非数值;0代表运算值, * 1代表+,-运算符;2代表*,x,X,/运算符;代表(,)小括号 * @param ch * @return */ public static int getCharOrder(char ch) { if(ch=='('||ch==')'){ return 3; } else if(ch=='*'||ch=='x'||ch=='X'||ch=='/') { return 2; } else if(ch=='+'||ch=='-') { return 1; } //.号说明是小数 else if (ch >= 48 && ch <= 57 ||ch=='.') { return 0; } return -1; } /** * 输入一个字符串,返回运算结果 * 过程为: * 字符串--->中缀表达式---->后缀表达式---->运算结果 * @param str 表达式 * @return 运算结果 */ public static double getResultByString(String str) { if(str==null||"".equals(str)) { throw new RuntimeException("表达式不正确"); } List<String> Expression= getExpression(str); List<String> suffixExpression = getSuffixExpression(Expression); double result=getResult(suffixExpression); return result; } }