zoukankan      html  css  js  c++  java
  • 【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 }

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

    具体示例过程如下:

  • 相关阅读:
    公告Ext3.3Bate发布了——PivotGrids, Calendars and 更多其他改进
    纪念一起工作三年的朋友的离开
    基于Ext.Panel扩展一个BMap
    Bing Map App 开发 还没入门遇见错误无法继续
    遗传算法学习笔记(2)
    接下来的目标
    Silverlight游戏开发心得(4)——重读调度器
    遗传算法学习笔记(5)
    Silverlight游戏开发心得(3)——有限状体机
    遗传算法学习笔记(4)
  • 原文地址:https://www.cnblogs.com/sxdcgaq8080/p/6270341.html
Copyright © 2011-2022 走看看