数据结构Java实现06----中缀表达式转换为后缀表达式

简介:

本文主要内容:

  • 表达式的三种形式
  • 中缀表达式与后缀表达式转换算法

一、表达式的三种形式:

  • 中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3。我们从小做数学题时,一直使用的就是中缀表达式。
  • 后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则),如:2 1 + 3 *。又比如3+(6-4/2)*5=23的后缀表达式为:3642/-5*+# (#符号为结束符)
  • 前缀表达式:同后缀表达式一样,不包含括号,运算符放在两个运算对象的前面,如:* + 2 1 3 。前缀表达式和后缀表达式其实是差不多的,只不过符号位置不同而已,前缀表达式不是很常见。

 

二、中缀表达式转换为后缀表达式:(思路)

1、将中缀表达式转换为后缀表达式:(步骤,有点难理解)

(1)当读到数字直接送至输出队列中;

(2)当读到运算符t时:

  a.将栈中所有优先级高于或等于t的运算符弹出,送到输出队列中;

    注:这句话不好理解,可以说成这样,从栈顶开始,依次弹出比当前处理的运算符优先级高的运算符,直到一个比它优先级低的或者遇到了一个左括号就停止

  b.t进栈;

(3)读到左括号时总是将它压入栈中;

(4)读到右括号时,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号;

(5)中缀表达式全部读完后,若栈中仍有运算符,将其送到输出队列中。

 

举例:

124b3dd7-f3b3-4110-904c-8a2b1d85dccd

上图中,左侧的那一列为输出序列,右侧的那一列为栈。

2、运用后缀表达式进行计算:

  (1)建立一个栈S;

  (2)从左到右读后缀表达式,读到数字就将它转换为数值压入栈S中,读到运算符则从栈中依次弹出两个数分别到Y和X,然后以“X 运算符 Y”的形式计算机出结果,再压加栈S中;

  (3)如果后缀表达式未读完,就重复上面过程,最后输出栈顶的数值则为结束。

举例:

3+(2-5)*6/3=-3 ,其后缀表达式为:325-6*3/+。其运算结果如下:

45270e43-7c61-4ac2-af8f-efb437e8d742

三、代码实现:将中缀表达式转换为后缀表达式

  • JDK  Stack类使用
  • 使用泛型

代码实现:

(1)StringToArithmetic.java:(中缀表达式转化为后缀表达式的工具类

复制代码
  1 /**
  2  * Created by smyhvae on 2015/9/7.
  3  * 工具类:
  4  * 1、中缀表达式转化为后缀表达式
  5  * 2、给出一个算术表达式(中缀表达式),直接得到计算结果
  6  */
  7 
  8 import java.util.Stack;
  9 import java.util.regex.Pattern;
 10 
 11 public class StringToArithmetic {
 12 
 13     private StringToArithmetic() {
 14     }
 15 
 16     //方法:给出一个算术表达式(中缀表达式),得到计算结果。 例如 (5+8+10)*1,返回23
 17     public static double stringToArithmetic(String string) {
 18         return suffixToArithmetic(infixToSuffix(string));
 19     }
 20 
 21     /**
 22      * 中缀表达式转后缀表达式 只处理了+,-,*,/和括号,没有处理负号及其它运算符,也没对前缀表达式验证。
 23      * 如要处理负号,可对表达式进行预转义处理,当下面条件成立时,将负号换成单目运算符"!" infix.charAt[i]=='-'&&(
 24      * i==0||infix.charAt[i-1]=='(')
 25      * 3*6/4+3
 26      * 3+6-4           3 6 + 4 -
 27      * 3+(6-4/2)*5    3 6 4 2 / - 5 * +
 28      */
 29     //方法:中缀表达式转成后缀表达式
 30     public static String infixToSuffix(String infix) {
 31         Stack<Character> stack = new Stack<Character>();
 32         String suffix = "";
 33         int length = infix.length();
 34         for (int i = 0; i < length; i++) {
 35             Character temp;
 36             char c = infix.charAt(i);
 37             switch (c) {
 38                 // 忽略空格
 39                 case ' ':
 40                     break;
 41                 // 碰到'(',push到栈
 42                 case '(':
 43                     stack.push(c);
 44                     break;
 45                 // 碰到'+''-',将栈中所有运算符弹出,送到输出队列中
 46                 case '+':
 47                 case '-':
 48                     while (stack.size() != 0) {
 49                         temp = stack.pop();
 50                         if (temp == '(') {
 51                             stack.push('(');
 52                             break;
 53                         }
 54                         suffix += " " + temp;
 55                     }
 56                     stack.push(c);
 57                     suffix += " ";
 58                     break;
 59                 // 碰到'*''/',将栈中所有乘除运算符弹出,送到输出队列中
 60                 case '*':
 61                 case '/':
 62                     while (stack.size() != 0) {
 63                         temp = stack.pop();
 64                         if (temp == '(' || temp == '+' || temp == '-') {
 65                             stack.push(temp);
 66                             break;
 67                         } else {
 68                             suffix += " " + temp;
 69                         }
 70                     }
 71                     stack.push(c);
 72                     suffix += " ";
 73                     break;
 74                 // 碰到右括号,将靠近栈顶的第一个左括号上面的运算符全部依次弹出,送至输出队列后,再丢弃左括号
 75                 case ')':
 76                     while (stack.size() != 0) {
 77                         temp = stack.pop();
 78                         if (temp == '(')
 79                             break;
 80                         else
 81                             suffix += " " + temp;
 82                     }
 83                     // suffix += " ";
 84                     break;
 85                 //如果是数字,直接送至输出序列
 86                 default:
 87                     suffix += c;
 88             }
 89         }
 90 
 91         //如果栈不为空,把剩余的运算符依次弹出,送至输出序列。
 92         while (stack.size() != 0) {
 93             suffix += " " + stack.pop();
 94         }
 95         return suffix;
 96     }
 97 
 98 
 99     /**
100      * postfix
101      *
102      * @return double
103      */
104     //方法:通过后缀表达式求出算术结果
105     public static double suffixToArithmetic(String postfix) {
106 
107         Pattern pattern = Pattern.compile("\\d+||(\\d+\\.\\d+)"); //使用正则表达式 匹配数字
108         String strings[] = postfix.split(" ");  //将字符串转化为字符串数组
109         for (int i = 0; i < strings.length; i++)
110             strings[i].trim();  //去掉字符串首尾的空格
111         Stack<Double> stack = new Stack<Double>();
112 
113         for (int i = 0; i < strings.length; i++) {
114 
115             if (strings[i].equals(""))
116                 continue;
117 
118             //如果是数字,则进栈
119             if ((pattern.matcher(strings[i])).matches()) {
120 
121                 stack.push(Double.parseDouble(strings[i]));
122             } else {
123                 //如果是运算符,弹出运算数,计算结果。
124                 double y = stack.pop();
125                 double x = stack.pop();
126                 stack.push(caculate(x, y, strings[i])); //将运算结果重新压入栈。
127             }
128         }
129         return stack.pop(); //弹出栈顶元素就是运算最终结果。
130 
131     }
132 
133     private static double caculate(double x, double y, String simble) {
134         if (simble.trim().equals("+"))
135             return x + y;
136         if (simble.trim().equals("-"))
137             return x - y;
138         if (simble.trim().equals("*"))
139             return x * y;
140         if (simble.trim().equals("/"))
141             return x / y;
142         return 0;
143     }
144 }
复制代码

(2)Test.java:(测试类)

复制代码
 1 public class Test {
 2     public static void main(String[] args) {
 3 
 4         String str = "3+(2-5)*6/3";  //其后缀表达式为325-6*3/+
 5 
 6         //调用方法:中缀表达式转成后缀表达式
 7         System.out.println(StringToArithmetic.infixToSuffix(str));
 8 
 9         //调用方法:给出一个算术表达式(中缀表达式),得到计算结果
10         System.out.println(StringToArithmetic.stringToArithmetic(str));
11 
12     }
13 
14 }
复制代码

上方代码中,第07行是根据中缀表达式算出后缀表达式。

第10行:是给出一个中缀表达式,直接的到计算结果,其实它的步骤是:先根据中缀表达式得到后缀表达式,然后根据后缀表达式去计算结果

运行效果:

68bb3685-b736-4d3b-95ad-6a6981b80071

相关文章
|
1月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
70 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
27天前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
42 1
|
29天前
|
存储 Java
告别混乱!用Java Map优雅管理你的数据结构
【10月更文挑战第17天】在软件开发中,随着项目复杂度增加,数据结构的组织和管理至关重要。Java中的Map接口提供了一种优雅的解决方案,帮助我们高效、清晰地管理数据。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,有效提升了代码质量和维护性。
81 2
|
29天前
|
存储 Java 开发者
Java Map实战:用HashMap和TreeMap轻松解决复杂数据结构问题!
【10月更文挑战第17天】本文深入探讨了Java中HashMap和TreeMap两种Map类型的特性和应用场景。HashMap基于哈希表实现,支持高效的数据操作且允许键值为null;TreeMap基于红黑树实现,支持自然排序或自定义排序,确保元素有序。文章通过具体示例展示了两者的实战应用,帮助开发者根据实际需求选择合适的数据结构,提高开发效率。
60 2
|
9天前
|
Java
探索Java中的Lambda表达式
【10月更文挑战第37天】本文将带你深入理解Java的Lambda表达式,从基础语法到高级特性,通过实例讲解其在函数式编程中的应用。我们还将探讨Lambda表达式如何简化代码、提高开发效率,并讨论其在实际项目中的应用。
|
12天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
35 6
|
12天前
|
Java API
Java中的Lambda表达式与函数式编程####
【10月更文挑战第29天】 本文将深入探讨Java中Lambda表达式的实现及其在函数式编程中的应用。通过对比传统方法,我们将揭示Lambda如何简化代码、提高可读性和维护性。文章还将展示一些实际案例,帮助读者更好地理解和应用Lambda表达式。 ####
|
12天前
|
JSON 自然语言处理 Java
这款轻量级 Java 表达式引擎,真不错!
AviatorScript 是一个高性能、轻量级的脚本语言,基于 JVM(包括 Android 平台)。它支持数字、字符串、正则表达式、布尔值等基本类型,以及所有 Java 运算符。主要特性包括函数式编程、大整数和高精度运算、完整的脚本语法、丰富的内置函数和自定义函数支持。适用于规则判断、公式计算、动态脚本控制等场景。
|
18天前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
16天前
|
Java API 开发者
Java中的Lambda表达式与函数式编程####
在Java的演变过程中,Lambda表达式和函数式编程的引入无疑是一次重大的飞跃。本文将深入探讨Lambda表达式的定义、用法及优势,并结合实例说明如何在Java中利用Lambda表达式进行函数式编程。通过对比传统编程方式,揭示Lambda表达式如何简化代码、提高开发效率和可维护性。 ####

热门文章

最新文章