【java】中缀表达式转后缀表达式 java实现

算法:

中缀表达式转后缀表达式的方法:
1.遇到操作数:直接输出(添加到后缀表达式中)
2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素【栈内的栈顶运算符>=遇到的运算符,就弹出】,然后将该运算符入栈
6.最终将栈中的元素依次出栈,输出。

 

例如:【5+4*6/2+3+(4*5)/5】 =24

转化之后的后缀表达式:【5 4 6 * 2 / + 3 + 4 5 *5 / +】

 

下面使用java实现 中缀表达式转化后缀表达式。  【支持多位数字,支持小数,支持+-*/()运算符】

  1 package com.agen.exchangePox;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Arrays;
  5 import java.util.HashMap;
  6 import java.util.List;
  7 import java.util.Map;
  8 import java.util.stream.Collectors;
  9 
 10 import org.junit.Test;
 11 
 12 public class InfixInToSuffix {
 13     /**
 14      *提前将 符号的优先级定义好
 15      */
 16     private static final Map<Character, Integer> basic = new HashMap<Character, Integer>();
 17     static {
 18         basic.put('-', 1);
 19         basic.put('+', 1);
 20         basic.put('*', 2);
 21         basic.put('/', 2);
 22         basic.put('(', 0);//在运算中  ()的优先级最高,但是此处因程序中需要 故设置为0
 23     }
 24     
 25     @Test
 26     public void test(){
 27         String a = toSuffix("55.6+4*60/2+33+(4.7*5.6)/5");//传入 一串 算数公式  
 28         System.out.println(a);
 29         System.out.println(dealEquation(a));
 30         
 31         
 32     }
 33     
 34     /**
 35      * 将  中缀表达式  转化为  后缀表达式
 36      */
 37     public String toSuffix(String infix){
 38         List<String> queue = new ArrayList<String>();                                    //定义队列  用于存储 数字  以及最后的  后缀表达式
 39         List<Character> stack = new ArrayList<Character>();                             //定义栈    用于存储  运算符  最后stack中会被 弹空
 40         
 41         char[] charArr = infix.trim().toCharArray();                                    //字符数组  用于拆分数字或符号
 42         String standard = "*/+-()";                                                        //判定标准 将表达式中会出现的运算符写出来
 43         char ch = '&';                                                                    //在循环中用来保存 字符数组的当前循环变量的  这里仅仅是初始化一个值  没有意义
 44         int len = 0;                                                                    //用于记录字符长度 【例如100*2,则记录的len为3 到时候截取字符串的前三位就是数字】
 45         for (int i = 0; i < charArr.length; i++) {                                        //开始迭代
 46             
 47             ch = charArr[i];                                                            //保存当前迭代变量
 48             if(Character.isDigit(ch)) {                                                    //如果当前变量为 数字  
 49                 len++;    
 50             }else if(Character.isLetter(ch)) {                                            //如果当前变量为  字母
 51                 len++;
 52             }else if(ch == '.'){                                                        //如果当前变量为  .  会出现在小数里面
 53                 len++;
 54             }else if(Character.isSpaceChar(ch)) {                                        //如果当前变量为 空格  支持表达式中有空格出现
 55                 if(len > 0) {                                                            //若为空格 代表 一段结束 ,就可以往队列中  存入了  【例如100 * 2  100后面有空格 就可以将空格之前的存入队列了】
 56                     queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i)));    //往 队列存入 截取的 字符串 
 57                     len = 0;                                                            //长度置空
 58                 }
 59                 continue;                                                                //如果空格出现,则一段结束  跳出本次循环
 60             }else if(standard.indexOf(ch) != -1) {                                        //如果是上面标准中的 任意一个符号
 61                 if(len > 0) {                                                            //长度也有
 62                     queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len, i)));    //说明符号之前的可以截取下来做数字
 63                     len = 0;                                                            //长度置空
 64                 }
 65                 if(ch == '(') {                                                            //如果是左括号
 66                     stack.add(ch);                                                        //将左括号 放入栈中
 67                     continue;                                                            //跳出本次循环  继续找下一个位置
 68                 }
 69                 if (!stack.isEmpty()) {                                                    //如果栈不为empty
 70                     int size = stack.size() - 1;                                        //获取栈的大小-1  即代表栈最后一个元素的下标
 71                     boolean flag = false;                                                //设置标志位
 72                     while (size >= 0 && ch == ')' && stack.get(size) != '(') {            //若当前ch为右括号,则 栈里元素从栈顶一直弹出,直到弹出到 左括号
 73                         queue.add(String.valueOf(stack.remove(size)));                    //注意此处条件:ch并未入栈,所以并未插入队列中;同样直到找到左括号的时候,循环结束了,所以左括号也不会放入队列中【也就是:后缀表达式中不会出现括号】
 74                         size--;                                                            //size-- 保证下标永远在栈最后一个元素【栈中概念:指针永远指在栈顶元素】
 75                         flag = true;                                                    //设置标志位为true  表明一直在取()中的元素
 76                     }
 77                     while (size >= 0 && !flag && basic.get(stack.get(size)) >= basic.get(ch)) {    //若取得不是()内的元素,并且当前栈顶元素的优先级>=对比元素 那就出栈插入队列
 78                         queue.add(String.valueOf(stack.remove(size)));                    //同样  此处也是remove()方法,既能得到要获取的元素,也能将栈中元素移除掉
 79                         size--;
 80                     }
 81                 }
 82                 if(ch != ')') {                                                            //若当前元素不是右括号  
 83                     stack.add(ch);                                                        //就要保证这个符号 入栈
 84                 } else {                                                                //否则就要出栈 栈内符号
 85                     stack.remove(stack.size() - 1);
 86                 }
 87             }
 88             if(i == charArr.length - 1) {                                                //如果已经走到了  中缀表达式的最后一位
 89                 if(len > 0) {                                                            //如果len>0  就截取数字
 90                     queue.add(String.valueOf(Arrays.copyOfRange(charArr, i - len+1, i+1)));
 91                 }    
 92                 int size = stack.size() - 1;                                            //size表示栈内最后一个元素下标
 93                 while (size >= 0) {                                                        //一直将栈内  符号全部出栈 并且加入队列中  【最终的后缀表达式是存放在队列中的,而栈内最后会被弹空】
 94                     queue.add(String.valueOf(stack.remove(size)));
 95                     size--;
 96                 }
 97             }
 98             
 99         }
100         return queue.stream().collect(Collectors.joining(","));                            //将队列中元素以,分割 返回字符串
101     }
102     
103 
104     /**
105      * 将 后缀表达式 进行  运算 计算出结果
106      * @param equation
107      * @return
108      */
109     public String dealEquation(String equation){
110         String [] arr = equation.split(",");                                    //根据, 拆分字符串
111         List<String> list = new ArrayList<String>();                            //用于计算时  存储运算过程的集合【例如list中当前放置  100   20  5  /  则取出20/5 最终将结果4存入list   此时list中结果为  100  4 】
112         
113         
114         for (int i = 0; i < arr.length; i++) {                                    //此处就是上面说的运算过程, 因为list.remove的缘故,所以取出最后一个数个最后两个数  都是size-2
115             int size = list.size();
116             switch (arr[i]) {
117             case "+": double a = Double.parseDouble(list.remove(size-2))+ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(a));     break;
118             case "-": double b = Double.parseDouble(list.remove(size-2))- Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(b));     break;
119             case "*": double c = Double.parseDouble(list.remove(size-2))* Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(c));     break;
120             case "/": double d = Double.parseDouble(list.remove(size-2))/ Double.parseDouble(list.remove(size-2)); list.add(String.valueOf(d));       break;
121             default: list.add(arr[i]);     break;                                    //如果是数字  直接放进list中
122             }
123         }
124         
125         return list.size() == 1 ? list.get(0) : "运算失败" ;                    //最终list中仅有一个结果,否则就是算错了
126     }
127     
128     
129 
130 }

 

 

其中的解释比较详细,不再赘述!!!

具体示例过程如下:

 

posted @ 2017-01-10 18:03  Angel挤一挤  阅读(9996)  评论(0编辑  收藏  举报