[Code] 中缀式转后缀式
[Code] 中缀式转后缀式
概要
对于一个可带括号的中缀四则运算表达式, 例如30 + 4 / 2
或 30 / ( 4 + 2 )
, 下面代码将分别转换为对应的后缀表达形式 30 4 2 / +
和 30 4 2 + /
. 要求每个 token 之间以若干个空白符隔开, 输入的中缀式为单行.
代码
import java.util.Scanner;
import java.util.Deque;
import java.util.ArrayDeque;
import java.util.Map;
public class Convertor {
public static void main(String[] main) {
Scanner in = new Scanner(System.in);
String expression = in.nextLine();
expression = "( " + expression + " )";
String[] tokens = expression.split("\\s+");
Deque<String> opStack = new ArrayDeque<>();
Deque<String> nuStack = new ArrayDeque<>();
Map<String, Integer> opPriority =
Map.of("+", 0, "-", 0, "*", 1, "/", 1, "(", -1);
for (String token: tokens) {
if (token.equals("(")) {
opStack.addFirst(token);
} else if (token.equals(")")) {
while (!opStack.peekFirst().equals("(")) {
produceOne(opStack, nuStack);
}
opStack.removeFirst();
} else if (opPriority.containsKey(token)) {
while ((!opStack.isEmpty()) && (opPriority.get(token) <= opPriority.get(opStack.peekFirst()))) {
produceOne(opStack, nuStack);
}
opStack.addFirst(token);
} else { // number
nuStack.addFirst(token);
}
}
System.out.println(nuStack.removeFirst().replaceAll("\\s+", " ").trim());
}
private static void produceOne(Deque<String> opStack, Deque<String> nuStack) {
String production = filter(nuStack.removeFirst()) + " ";
production = filter(nuStack.removeFirst()) + " " + production + " ";
production = production + " " + opStack.removeFirst() + " ";
nuStack.addFirst(production);
}
private static String filter(String token) {
return token.equals("@") ? "" : token;
}
}
分析
- 为了统一处理(避免分类讨论), 对于输入的中缀表达式直接加上两端的括号. 这样的操作并不会影响整个求解的结果, 而不加这个括号需要额外处理最终操作符栈剩余的操作符.
- 逐个 token 处理,
- 对于操作数, 直接入栈.
- 左右括号配对处理.
- 对于一般的操作符, 在此处充当 trigger 的作用. 逻辑上, 第一个操作符入栈, 对于后续的操作符, 先逐个弹出操作符栈中优先级不小于当前操作符的运算符以及相应的操作数, 在将当前的操作符入栈. 弹出优先级大的操作符是显然的, 弹出优先级相等的操作符是由于要满足左结合性, 若是右结合操作符, 则不弹出. 注意弹出操作符并产生代表运算结果的字符串后仍需将其当做结果压回操作数栈中.
- 细节上,
- 使用 Java 9 的
Map.of
函数简化opPriority
字典的构建代码. - 使用效率更高实现更完备的
Deque
并将操作限制在栈操作上以代替不再推荐的Stack
. - 为了简化讨论, 将
(
的优先级定义为最低. - 为了简化讨论, 先在各结果 token 之间插入若干个空白符, 输出时再统一压缩多余的空白符.
- 使用 Java 9 的
- 假定输入都是合法的, 没有对不满足概要中假设的前提的非法输入进行处理.
[Code] 中缀式转后缀式的更多相关文章
- NYOJ467 中缀式变后缀式 【栈】
中缀式变后缀式 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描写叙述 人们的日常习惯是把算术表达式写成中缀式,但对于机器来说更"习惯于"后缀式.关于算术 ...
- NYOJ 467 中缀式变后缀式
做了表达式求值那道题之后做的 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描写叙述 人们的日常习惯是把算术表达式写成中缀式,但对于机器来说更"习惯于"后 ...
- nyoj 467 中缀式变后缀式 (栈)
中缀式变后缀式 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 人们的日常习惯是把算术表达式写成中缀式,但对于机器来说更“习惯于”后缀式,关于算术表达式的中缀式和后缀 ...
- NYOJ--257--郁闷的C小加(一)(中缀表达式变后缀表达式 )
郁闷的C小加(一) 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 我们熟悉的表达式如a+b.a+b*(c+d)等都属于中缀表达式.中缀表达式就是(对于双目运算符来说 ...
- 栈的简单应用之中缀表达式转后缀表达式(C语言实现逆波兰式)
一.前言 普通人在书写计算式时会选择中缀表达式,这样符合人脑的认知习惯.可计算机处理时后缀表达式才能使处理速度更快,其原因是利用堆栈结构减少计算机内存访问.同时它也是一个很好锻炼栈这个数据结构的应 ...
- SDUT 2133 数据结构实验之栈三:后缀式求值
数据结构实验之栈三:后缀式求值 Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 对于一个基于二元运算符的后缀表示式(基本操作数都是 ...
- SDUT-2133_数据结构实验之栈与队列三:后缀式求值
数据结构实验之栈与队列三:后缀式求值 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 对于一个基于二元运算符的后缀表示式 ...
- SDUT-2132_数据结构实验之栈与队列二:一般算术表达式转换成后缀式
数据结构实验之栈与队列二:一般算术表达式转换成后缀式 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 对于一个基于二元运 ...
- javascript使用栈结构将中缀表达式转换为后缀表达式并计算值
1.概念 你可能听说过表达式,a+b,a+b*c这些,但是前缀表达式,前缀记法,中缀表达式,波兰式,后缀表达式,后缀记法,逆波兰式这些都是也是表达式. a+b,a+b*c这些看上去比较正常的是中缀表达 ...
随机推荐
- Oracle通过JOB定时执行存储过程实现两表数据比对
需求: 第三方云平台管理的虚拟机会进行关机.资源扩展等操作,因此开关机状态.CPU.内存.磁盘大小等数据需要进行同步.这里第三方云平台是BMC CLM云平台,底层虚拟化平台是Vcenter.进行同步的 ...
- junit测试延伸--方法的重复测试
在实际编码测试中,我们有的时候需要对一个方法进行多次测试,那么怎么办呢?这个问题和测试套件解决的方案一样,我们总不能不停的去右键run as,那怎么办呢?还好伟大的junit帮我们想到了. OK,现在 ...
- Linux指令--tar,gzip
通过SSH访问服务器,难免会要用到压缩,解压缩,打包,解包等,这时候tar命令就是是必不可少的一个功能强大的工具.linux中最流行的tar是麻雀虽小,五脏俱全,功能强大. tar命令可以为linux ...
- WebSphere--定制配置
本节介绍如何启动和使用 WebSphere应用服务器的管理器(一个图形界面)为 Servlet 活动和 WebSphere应用服务器的组件定制基本设置参数. 1.启动 WebSphere应用服务 ...
- Linkin大话eclipse快捷键
刚来这家公司的时候,作为菜鸟的我在帮别人调试代码的时候,有人说我快捷键使用的很熟悉. 呵呵,工欲善其事必先利其器,以下这些快捷键是最常用的也是要必须记住的. [Ctrl开头] Ctrl+1:快速修复 ...
- HSSF、XSSF和SXSSF区别以及Excel导出优化
之前有写过运用POI的HSSF方式导出数据到Excel(见:springMVC中使用POI方式导出excel至客户端.服务器实例),但这种方式当数据量大到一定程度时容易出现内存溢出等问题. 首先,PO ...
- 【转】linux grep命令
1.作用 Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来 2.格式 grep [options] 3.主要参数 [options]主要参数: - ...
- Java NIO 之 Socket Channel
在Java NIO中用Channel来对程序与进行I/O操作主体的连接关系进行抽象,这些IO主体包括如文件.Socket或其他设备.简而言之,指代了一种与IO操作对象间的连接关系. 按照Channel ...
- ArcSDE 10.1安装、配置、连接
ArcSDE 10.1安装.配置.连接 (SQL Server 2008) 1 概述 ArcSDE 10.1的安装配置相较于ArcSDE 10.0和之前版本,有了一些显著的变化,比如取消了Post ...
- Yii框架中使用mongodb扩展
前提条件:安装了mongodb数据库 安装了mongo的php驱动 下载Yii的mongo扩展:这是YiiMongoDbSuite的1.3.6版本支持PHP Mongo驱动的版本为1.0.5及以下 下 ...