【Java数据结构的实现】之系列三栈的实现(使用栈计算后缀表达式)

简介:

【Java数据结构的实现】之系列三栈的实现(使用栈计算后缀表达式)

上讲介绍了栈的介绍,最后并给出了栈的抽象数据类型

1.1本章学习目标

  • 中、后缀表达式简介
  • 后缀表达式的实现

本文介绍了栈的实例--使用栈计算后缀表达式:

1.2 中、后缀表达式简介

①中缀表达式:

       通常,算术表达式写作中缀表达式,,什么是中缀表达式呢?中缀表达式就是:操作符位于操作数之间。

如下形式:

<操作数><操作符><操作数>

例如表达式:1+2*3,计算时,我们根据表达式的优先规则来计算。其结果是7而不是9.

那什么是后缀表达式呢?

②后缀表达式:

后缀表达式就是:操作符位于两个操作数之后,后缀表达式的形式如下:

<操作数><操作数><操作符>

如下所示:

 

 
  1. 1 2 - 等价于1-2  
  2.  

③使用后缀表达式的优点:

      后缀表达式比中缀表达式更容易计算,因为它不用考虑优先规则和括弧,表达式中的操作数和操作符的顺序就足以完成计算。

因此程序设计语言编辑器和运行时环境在其内部中往往使用后缀表达式。

④后缀表达式的计算规则:

        后缀表达式的计算过程可以概括如下:

从左到右扫描整个表达式,把每个操作符应用到其之前两个相邻的操作数,并计算该结果,剩下的表达式以此类推。

1+2*3

可以转换成后缀表达式如下:

1 2 3 * +

计算过程如下:

1 2*3 + --> 1 6 + -->7

更复杂的后缀表达式,亦是如此规则。由此可以发现,栈是用于计算后缀表达式的理想数据结构。

1.3 后缀表达式的实现

①程序设计的思路:

 
  1. /**  
  2.      * 从左到右扫描表达式,以此标识出每个符号(操作数或操作符)。如果是操作数,  
  3.      * 则把它压入栈中。如果是操作符,则从栈中弹出两个元素,  
  4.      * 并把该操作符应用在这两个元素只上,然后把操作结果压入栈中。  
  5.      * 当到达表达式的末尾时,栈中所神域的元素就是该表达式的计算结果。  
  6.      * @param expr 后缀表达式  
  7.      * @return int 后缀表达式的值  
  8.      * */ 


程序运行时,会提示用户反复输入操作数和操作符,中间已空格隔开。

②程序关键部位均有详细的注释!

 

 
  1. import java.util.Stack;  
  2.  
  3. /**  
  4.  * 计算后缀表达式,假定操作数都是常量  
  5.  * */ 
  6. public class PostfixEvaluator {  
  7.     /**+号标识*/ 
  8.     private final char ADD = '+';  
  9.     /**-号标识*/ 
  10.     private final char SUBTRACT = '-';  
  11.     /***号标识*/ 
  12.     private final char MULTIPLY = '*';  
  13.     /**除号标识*/ 
  14.     private final char DIVIDE = '/';  
  15.     /**栈*/ 
  16.     private Stack<Integer> stack;  
  17.     /**创建一个新栈*/ 
  18.     public PostfixEvaluator(){  
  19.         stack = new Stack<Integer>();  
  20.     }  
  21.     /**  
  22.      * 从左到右扫描表达式,以此标识出每个符号(操作数或操作符)。如果是操作数,  
  23.      * 则把它压入栈中。如果是操作符,则从栈中弹出两个元素,  
  24.      * 并把该操作符应用在这两个元素只上,然后把操作结果压入栈中。  
  25.      * 当到达表达式的末尾时,栈中所神域的元素就是该表达式的计算结果。  
  26.      * @param expr 后缀表达式  
  27.      * @return int 后缀表达式的值  
  28.      * */ 
  29.  
  30.     public int evaluate(String expr){  
  31.         int op1,op2,result=0;  
  32.         String token;  
  33.         //将字符串分解,\s 匹配任何空白字符,包括空格、制表符、换页符等。   
  34.         String[] tokenizer = expr.split("\\s");  
  35.         for (int x = 0; x < tokenizer.length; x++){  
  36.             System.out.print(tokenizer[x]+" ");//输出  
  37.             token = tokenizer[x];  
  38.             if(isOperator(token)){//判断是操作符,则出栈两个操作数  
  39.                 op2 = (stack.pop()).intValue();  
  40.                 op1 = (stack.pop()).intValue();  
  41.                 result = evalSingleOp (token.charAt(0),op1,op2);//计算结果  
  42.                 stack.push(new Integer(result));//把计算结果压入栈中  
  43.             }else {  
  44.                 stack.push(new Integer(Integer.parseInt(token)));//压入操作数  
  45.             }  
  46.         }  
  47.         return result;  
  48.     }  
  49.     /**  
  50.      * 计算  
  51.      * @param1 op1 第一个操作数  
  52.      * @prama2 op2第二个操作数  
  53.      * @return 计算的结果  
  54.      *   
  55.      * */ 
  56.     private int evalSingleOp(char operation, int op1, int op2) {  
  57.         int result = 0;  
  58.         switch(operation)  
  59.         {  
  60.             case ADD:  
  61.                 result = op1+op2;  
  62.                 break;  
  63.             case SUBTRACT:  
  64.                 result = op1-op2;  
  65.                 break;  
  66.             case MULTIPLY:  
  67.                 result = op1*op2;  
  68.                 break;  
  69.             case DIVIDE:  
  70.                 result = op1/op2;  
  71.                 break;  
  72.         }  
  73.         return result;  
  74.     }  
  75.     /**  
  76.      * 判断是否为操作符  
  77.      * @param token  
  78.      * @return boolean   
  79.      * */ 
  80.     private boolean isOperator(String token) {  
  81.            
  82.         return (token.equals("+")||token.equals("-")||  
  83.                token.equals("*")||token.equals("/"));  
  84.     }  
  85. }  

③ 测试方法:

 

 
  1. import java.util.Scanner;  
  2.  
  3. /**  
  4.  *   
  5.  * 计算后缀表达式  
  6.  * */ 
  7. public class Postfix {  
  8.  
  9.     /**  
  10.      * @param args  
  11.      */ 
  12.     public static void main(String[] args) {  
  13.         String expression,again;  
  14.         int result;  
  15.         try {  
  16.             Scanner in = new Scanner(System.in);  
  17.             do {  
  18.                 PostfixEvaluator evaluator = new PostfixEvaluator();  
  19.                 System.out.println("请输入一个后缀表达式");  
  20.                 expression = in.nextLine();  
  21.                 result = evaluator.evaluate(expression);//  
  22.                 System.out.println();  
  23.                 System.out.println("计算结果为:"+result);  
  24.                 System.out.println("计算另外一个表达式【Y/N】?:");  
  25.                 again = in.nextLine();  
  26.                 if(again.equalsIgnoreCase("n")){  
  27.                     System.out.println("计算退出!");  
  28.                 }  
  29.                 System.out.println();  
  30.             }while (again.equalsIgnoreCase("y"));  
  31.         }catch(Exception e) {  
  32.             e.printStackTrace();  
  33.             System.out.println("输入异常,请正确输入后缀表达式,并以空格区分");  
  34.         }  
  35.  
  36.     }  
  37.       
  38.  

④测试结果:

 

 
  1. /**  
  2.  * 请输入一个后缀表达式  
  3. 3 4 * 2 5 + - 4 * 2 /  
  4. 3 4 * 2 5 + - 4 * 2 /   
  5. 计算结果为:10  
  6. 计算另外一个表达式【Y/N】?:  
  7.  *   
  8.  * */ 

 





 本文转自 w156445045 51CTO博客,原文链接:http://blog.51cto.com/enetq/713534,如需转载请自行联系原作者


相关文章
|
2月前
|
Java
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
【Java】如果一个集合中类型是String如何使用拉姆达表达式 进行Bigdecimal类型计算?
29 0
|
2月前
|
存储 人工智能 算法
【数据结构-算法】:数据结构和算法的一些个人总结(Java实现)
【数据结构-算法】:数据结构和算法的一些个人总结(Java实现)
63 0
|
2月前
|
存储 算法 Java
Java数据结构与算法-java数据结构与算法(二)
Java数据结构与算法-java数据结构与算法
120 1
|
5天前
|
存储 监控 安全
JVM工作原理与实战(十六):运行时数据区-Java虚拟机栈
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了运行时数据区、Java虚拟机栈等内容。
11 0
|
12天前
|
安全 Java
【亮剑】Java中的`Future`接口代表异步计算结果,常与`ExecutorService`配合启动任务并获取结果
【4月更文挑战第30天】Java中的`Future`接口代表异步计算结果,常与`ExecutorService`配合启动任务并获取结果。`Future`接口提供`isDone()`、`get()`、`get(timeout, unit)`和`cancel(mayInterruptIfRunning)`等方法。`FutureTask`是`Future`的实现类,可作为`Runnable`执行并返回结果。
|
16天前
|
存储 安全 Java
Java程序员必须掌握的数据结构:HashMap
HashMap底层原理实现是每个Java Boy必须掌握的基本技能,HashMap也是业务开发每天都需要遇到的好伙伴。如此基础且核心的底层数据结构,JDK也给其赋予了线程安全的功能,我们来看看~
31 2
Java程序员必须掌握的数据结构:HashMap
|
17天前
|
存储 安全 Java
Java并发编程中的高效数据结构:ConcurrentHashMap解析
【4月更文挑战第25天】在多线程环境下,高效的数据访问和管理是至关重要的。Java提供了多种并发集合来处理这种情境,其中ConcurrentHashMap是最广泛使用的一个。本文将深入分析ConcurrentHashMap的内部工作原理、性能特点以及它如何在保证线程安全的同时提供高并发性,最后将展示其在实际开发中的应用示例。
|
18天前
|
存储 算法 安全
Java集合篇之逐渐被遗忘的Stack,手写一个栈你会吗?
Java集合篇之逐渐被遗忘的Stack,手写一个栈你会吗?
17 0
|
23天前
|
存储 供应链 Java
《Java 简易速速上手小册》第3章:Java 数据结构(2024 最新版)
《Java 简易速速上手小册》第3章:Java 数据结构(2024 最新版)
9 1
|
29天前
|
Java API
编码的奇迹:Java 21引入有序集合,数据结构再进化
编码的奇迹:Java 21引入有序集合,数据结构再进化
18 0