6, java数据结构和算法: 栈的应用, 逆波兰计算器, 中缀表达式--> 后缀表达式
直接上代码:
public class PolandCalculator {
//栈的应用:波兰计算器: 即: 输入一个字符串,来计算结果, 比如 1+((2+3)×4)-5 结果为16
public static void main(String[] args) throws Exception {
/**
* 思路:
* 1: 将 1+((2+3)×4)-5 (这叫中缀表达式,运算符再数字中间), 转换为后缀表达式 (1 2 3 + 4 × + 5 –)
* 2: 使用栈, 将后缀表达式 , 计算得出结果
*
* 因为 后缀表达式, 来计算会变得简单易懂, 不需要那么多的判断, 只需要 数入栈,然后判断运算符, 从栈中pop出二个数,计算,并把结果入栈, 循环往复,得到最终结果
*/
String str = "1+((2+3)*4)-5";
// 1, 先将 str 字符串变为对应的 中缀表达式 midExpressionList(便于显示)
List<String> midExpressionList = toMidExpressionList(str);
System.out.println("前缀表达式为: "+midExpressionList);
// 2, 将 midExpressionList 转换为 后缀表达式对应的 suffixExpressionList
List<String> suffixExpressionList = toSuffixExpressionList(midExpressionList);
System.out.println("后缀表达式为: "+suffixExpressionList);
// 3, 计算结果
calculator(suffixExpressionList);
}
private static List<String> toMidExpressionList(String s) {
//定义一个List,存放中缀表达式 对应的内容
List<String> ls = new ArrayList<String>();
int i = 0; //这时是一个指针,用于遍历 中缀表达式字符串
String str; // 对多位数的拼接
char c; // 每遍历到一个字符,就放入到c
do {
//如果c是一个非数字,我需要加入到ls
if((c=s.charAt(i)) < 48 || (c=s.charAt(i)) > 57) {
ls.add("" + c);
i++; //i需要后移
} else { //如果是一个数,需要考虑多位数
str = ""; //先将str 置成"" '0'[48]->'9'[57]
while(i < s.length() && (c=s.charAt(i)) >= 48 && (c=s.charAt(i)) <= 57) {
str += c;//拼接
i++;
}
ls.add(str);
}
}while(i < s.length());
return ls;//返回
}
private static List<String> toSuffixExpressionList(List<String> midExpressionList) {
//1, 定义一个栈 用来存运算符
Stack<String> cal = new Stack<String>();
//2, 定义一个list 来做存中间结果和返回, 也可以定义一个栈, 但是用栈的话, 这个转换过程并没有pop操作, 而且还要逆序显示,比较麻烦, 所以用list
List<String> resList = new ArrayList<String>();
for (String str : midExpressionList) {
if(str.matches("\\d+")){
//是一个或多个数字, 就存入resList
resList.add(str);
}else if (str.equals("(")){
//如果是 左括号 , 就加入cal 栈
cal.push(str);
}else if(str.equals(")")){
//如果是右括号, 此时需要将cal 栈的运算符号,依次pop,并加入到resList中, 直到遇到"左括号"停止, 最后将"左括号"删除
while(! cal.peek().equals("(")){
resList.add(cal.pop());
}
cal.pop();//跳出循环时,已经将"("之前的运算符都存入resList中, 此一步是将"("删除
}else {
//是运算符 +,-,*,/ , 如果是运算符, 如果cal栈为空,直接加入栈, 如果该运算符 优先级小于等于 cal栈顶运算符, 将cal栈中运算符 依次pop,加入到resList中, 知道运算符优先级大于为止
while(cal.size() != 0 && operator(str) <= operator(cal.peek())){
resList.add(cal.pop());
}
cal.push(str);
}
}
//最后将 cal栈中的运算符依次弹出加入到resList中
while(cal.size() != 0){
resList.add(cal.pop());
}
return resList;
}
private static int operator(String str) {
if(str.equals("+") || str.equals("-")){
return 1;
}
if(str.equals("*") || str.equals("/")){
return 2;
}
return 0;
}
private static void calculator(List<String> suffixExpressionList) throws Exception {
Stack<String> stack = new Stack<>();
for (String str : suffixExpressionList) {
if(str.matches("\\d+")){
//是数字, 入栈
stack.push(str);
}else{
//是运算符, 从栈中pop二个数, 计算,将计算结果存入stack中, 最终stack中的数, 就是计算结果
int num2 = Integer.parseInt(stack.pop());
int num1 = Integer.parseInt(stack.pop());
int res = 0;
if(str.equals("+")){
res = num1 + num2;
} else if(str.equals("-")){
res = num1 - num2;
} else if(str.equals("*")){
res = num1 * num2;
} else if(str.equals("/")){
res = num1 / num2;
} else{
throw new Exception("没有这个运算符:"+str);
}
//计算结果 入栈
stack.push(String.valueOf(res));
}
}
System.out.println("最终的计算结果为:" + stack.pop());
}
}
测试结果:

在测试一个:

6, java数据结构和算法: 栈的应用, 逆波兰计算器, 中缀表达式--> 后缀表达式的更多相关文章
- Java数据结构和算法(六):前缀、中缀、后缀表达式
前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆序,匹配关键字符等等,那它还有别的什么功能吗 ...
- Java数据结构和算法 - 栈和队列
Q: 栈.队列与数组的区别? A: 本篇主要涉及三种数据存储类型:栈.队列和优先级队列,它与数组主要有如下三个区别: A: (一)程序员工具 数组和其他的结构(栈.队列.链表.树等等)都适用于数据库应 ...
- java 数据结构与算法---栈
原理来自百度百科 一.栈的定义 栈是一种只能在一端进行插入和删除操作的特殊线性表:它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数 ...
- 5, java数据结构和算法: 栈 , 入栈, 出栈, 正序遍历,,逆序遍历
直接上代码: class ArrayStack{ //用数组模拟栈 int maxSize; int[] stack; int top = -1;//表示栈顶 public ArrayStack(in ...
- 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现
本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是 ...
- java数据结构与算法之栈(Stack)设计与实现
本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...
- Java数据结构和算法(一)--栈
栈: 英文名stack,特点是只允许访问最后插入的那个元素,也就是LIFO(后进先出) jdk中的stack源码: public class Stack<E> extends Vector ...
- Java数据结构和算法(六)——前缀、中缀、后缀表达式
前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆序,匹配关键字符等等,那它还有别的什么功能吗 ...
- Java数据结构和算法 - 二叉树
前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...
随机推荐
- Python中的输入(input)和输出打印
目录 最简单的打印 打印数字 打印字符 字符串的格式化输出 python中让输出不换行 以下的都是在Python3.X环境下的 使用 input 函数接收用户的输入,返回的是 str 字符串 最简单的 ...
- PowerShell-4.API调用以及DLL调用
PowerShell可以直接调用API,So...这东西完全和cmd不是一回事了... 调用API的时候几乎和C#一样(注意堆栈平衡): 调用MessageBox: $iii = Add-Type - ...
- <JVM下篇:性能监控与调优篇>04-JVM运行时参数
笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...
- Spring MVC工作原理及源码解析(三) HandlerMapping和HandlerAdapter实现原理及源码解析
1.HandlerMapping实现原理及源码解析 在前面讲解Spring MVC工作流程的时候我们说过,前端控制器收到请求后会调⽤处理器映射器(HandlerMapping),处理器映射器根据请求U ...
- Git 系列教程(7)- 撤销操作
撤销操作 在任何一个阶段,你都有可能想要撤销某些操作 有些撤销操作是不可逆的 --amend 修补提交 有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了. 此时,就可以运行带有 -- ...
- FPS游戏方框透视基本原理
计算机图形学基础 计算机图形学最基础的目标就是把建模时构建好的3D物体显示在2D屏幕上,这就涉及到物体在不同坐标系中坐标的转换.(物体/建模坐标系 ---------> 屏幕坐标系) 坐标系 在 ...
- 在Visual Studio 中使用git——文件管理-中(五)
在Visual Studio 中使用git--什么是Git(一) 在Visual Studio 中使用git--给Visual Studio安装 git插件(二) 在Visual Studio 中使用 ...
- markerdown基础
标题 用#+空格 字体 加粗两边两个** 斜体两边* 斜体加粗三个* 引用 '>' 分割线 三个---或者三个*** 图片 ![截图]() 超链接 点击跳转到文章 []+() 列表 1 + 点+ ...
- [设计模式] 读懂UML图
类之间关系(由强到弱) realize(继承):三角+实线(指向类),继承类(SUV是一种汽车) generalization(实现):三角+虚线(指向接口),实现接口(汽车是一种车) composi ...
- 009.kubernets的调度系统之污点和容忍
Taints和Tolerations(污点和容忍) Taint需要与Toleration配合使用,让pod避开那些不合适的node.在node上设置一个或多个Taint后,除非pod明确声明能够容忍这 ...