堆栈的经典应用,四则表达式的元算。这里只能操作的符号是:+ - * / ()。不支持大括号...
下面是代码:
package net.itaem.test; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Stack; /** * 堆栈的应用 * 使用这个堆栈完成四则表达式的运算 四则:+ - * // * 比如:3 + (15-1)*2 -10 = 21 * */ public class StackApply { //四则表达式,也就是中缀表达式 private String source; //程序不验证输入的表达式是否合法,所以请保证输入的表达式有效,否则计算结果可能无效 //要求结果的四则表达式 public StackApply(String source){ if(source == null || "".equals(source)) throw new RuntimeException("输入的表达式不能为空"); this.source = source; } //将中缀表达式变成后缀表达式 public List<String> toLaterPattern(){ //定义一个堆栈,用来保存操作符号 Stack<Character> calStack = new Stack<Character>(); //定义一个顺序表,用来存储表达式中的数字 List<Integer> intList = new LinkedList<Integer>(); //后缀表达式的最后结果 List<String> resultList = new ArrayList<String>(); //取出中缀表达式里面的全部数字 String[] intArrays = source.split("[^0-9]"); //将数字添加到集合中,并且去掉空值 for(String intArray: intArrays){ if(!"".equals(intArray)){ intList.add(Integer.parseInt(intArray)); } } int index = 0; int fromIndex = 0; //遍历后缀表达式 for(int i=0; i<source.length();){ //如果是数字,将数字添加到后缀表达式中 if(isNumber(source.charAt(i))){ //添加数值到结果集 resultList.add(intList.get(index) + ""); //查看这个数值占用的位数 int intLength = (intList.get(index) + "").length(); //修改下一个i的值 i = source.indexOf(intList.get(index) + "", fromIndex) + intLength; //记录下下一个数值的起始处 fromIndex = i; index++; } //如果是 + - * / ( ) 这四个符号,进行进出站操作 else if(isCalculator(source.charAt(i))){ //如果是‘(‘,进入堆栈 if(source.charAt(i) == ‘(‘){ calStack.add(source.charAt(i)); //弹出第一栈顶到第一个(之间的操作符号 }else if(‘)‘ == source.charAt(i)){ //将数字的内容出栈 Character pop = null; //输出()之间的内容 while((pop = calStack.pop()) != ‘(‘){ char[] p = new char[1]; p[0] = pop; //将出栈的内容添加到结果集中 resultList.add(new String(p)); } }else{ //这里处理 + - * /的情况 //是* / if(source.charAt(i) == ‘*‘ || source.charAt(i) == ‘/‘){ calStack.push(source.charAt(i)); //因为 * /的优先级比较高,直接压入堆栈之中 }else if(source.charAt(i) == ‘+‘ || source.charAt(i) == ‘-‘){ //判断堆栈里面的内容,看看优先级关系 if(calStack.isEmpty()){ //如果为空,直接添加进去堆栈之中 calStack.push(source.charAt(i)); }else{ //取出第一个运算符号,这里不是弹出 char pop = calStack.peek(); //查看是否是优先级比较高的符号 if(pop == ‘*‘ || pop == ‘/‘){ while(!calStack.isEmpty()){ //输出所有优先级比较高的运算符 pop = calStack.pop(); if(pop == ‘*‘ || pop == ‘/‘){ //如果是 * /,优先级比较高,压入到堆栈中 resultList.add(pop + ""); }else{ //优先级比较低,停止 break; } } //弹出完成之后,要将此次的操作符添加到堆栈中 calStack.push(source.charAt(i)); }else{ //如果是相同优先级的+ -,添加到堆栈之中 // 1-2-3-4不满足结合律,所以要特殊处理,将数字改变为负数 if(source.charAt(i) == ‘-‘ && pop == ‘-‘){ resultList.set(index-1, -intList.get(index-1) + ""); } calStack.push(source.charAt(i)); } } } } i++; } } //将堆栈里面所有的操作符号取出来 List<String> pops = new LinkedList<String>(); while(!calStack.isEmpty()){ pops.add(calStack.pop()+""); } for(String pop: pops){ resultList.add(pop); } return resultList; } public String each(char c){ return null; } private boolean isCalculator(char c) { switch(c){ case ‘+‘: case ‘-‘: case ‘*‘: case ‘/‘: case ‘(‘: case ‘)‘:return true; default:return false; } } //判断一个字符是否是数字 private boolean isNumber(char c) { switch(c){ case ‘0‘: case ‘1‘: case ‘2‘: case ‘3‘: case ‘4‘: case ‘5‘: case ‘6‘: case ‘7‘: case ‘8‘: case ‘9‘:return true; default:return false; } } //返回计算结果 public float result(){ //得到后缀运算表达式的内容 List<String> laterPattern = toLaterPattern(); //用来保存计算结果的堆栈 Stack<Float> floatStack = new Stack<Float>(); float calResult = 0; //计算结果 //计算过程:如果是数字,进堆栈,如果是运算操作符,出栈,然后执行运算,再将运算结果压入堆栈 for(String c: laterPattern){ if(c.matches("-?\\d+")){ //将数字取出来,然后压入堆栈中 //将数字压入到堆栈中 floatStack.push(Float.parseFloat(c)); }else{ //取出两个操作数 float first = floatStack.pop(); float second = 0; //处理是负数的情况 if(!floatStack.isEmpty()){ second = floatStack.pop(); } char choose = c.toCharArray()[0]; switch(choose){ case ‘+‘: calResult = second+first; break; case ‘-‘: //2-(-2)==4,所以这里要特殊处理 if(first > 0){ calResult = second - first; }else{ calResult = second + first; } break; case ‘*‘: calResult = second*first; break; case ‘/‘: calResult = second/first; //记得转为float,避免出现 3/2 == 1的情况 break; default:throw new RuntimeException("操作符有错误...目前暂且不支持+ - * / ( ) 之外的运算符"); } //将计算结果压入堆栈 floatStack.push(calResult); } } //最后一个栈顶元素就是结果 return floatStack.pop(); } public static void main(String[] args) { System.out.println("1+2+3+4 = " + new StackApply("1+2+3+4").result()); System.out.println("1+2+3*4 = " + new StackApply("1+2+3*4").result()); System.out.println("(-11)+2+3*4 = " + new StackApply("(-11)+2+3*4").result()); System.out.println("11+2/3*4 = " + new StackApply("11+2/3*4").result()); System.out.println("1*2*3*4 = " + new StackApply("1*2*3*4").result()); System.out.println("1/(2/(3/4)) = 1/2/3/4 = " + new StackApply("1/2/3/4").result() + " = " + new StackApply("1/2/3/4").result()); //相当于是 1/(2/(3/4)) System.out.println("1+2*3-1 = " + new StackApply("1+2*3-1").result()); System.out.println("1-2-3-4 = " + new StackApply("1-2-3-4").result()); } }
上面的代码可能有点乱,不过主要的思想就是堆栈的应用
运算结果:
1+2+3+4 = 10.0 1+2+3*4 = 15.0 (-11)+2+3*4 = 3.0 11+2/3*4 = 11.166667 1*2*3*4 = 24.0 1/(2/(3/4)) = 1/2/3/4 = 0.375 = 0.375 1+2*3-1 = 5.0 1-2-3-4 = -8.0
总结:堆栈是一个FIRST IN LAST OUT,典型的FILO的数据结构。在计算机中,应用很广泛,大家可以认真研究下...
时间: 2024-11-01 15:39:33