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数据结构和算法 - 二叉树
前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...
随机推荐
- hdu5062 简单题
题意: 求区间逆序数的个数,逆序数增加了个要求就是必须要是先升序在降序例如12321或者123321这样的. 思路: 水题直接写就行了,数据范围不大,估计直接求也不会超时,我 ...
- Java枚举类、注解和反射
本文主要介绍的是枚举类,注解和反射.还有一些基础知识:static,基本数据类型,运算符优先级放在文中,以便查阅复习. 其中牵扯到泛型的部分,可参考本人的另一篇博客:(Collection, List ...
- Charles的功能(web)
# 验证是否可以获取web端的https接口 1. 打开Charles 2.打开游览器输入数据 3. 查看Charles 4.从上图所看,能获取htpps的包数据,即可对web端进行抓包 4.char ...
- 初识Vue2(一):表单输入绑定(附Demo)
在线演示 http://demo.xiongze.net/ 下载地址 https://gitee.com/xiongze/Vue2.git js引用 <!--这里可以自己下载下来引用,也可以使用 ...
- 人人都爱Kubernetes,Docker难道就不香了吗?
开篇 提起Docker,有很多人第一印象会认为它就是一个虚拟化容器,所以大家特别容易陷入到一种误区,就是觉得Docker只是在Linux操作系统之上又增加了一层,就跟OS上跑了一个VMWare一样.D ...
- CRM系统实施的原则
在我们使用CRM系统服务企业和客户之前,需要先系统的实施它.使用CRM系统却没有发挥它应有价值的案例很多,那么我们要怎样才能让CRM的作用发挥到最大,并确保它是成功的?那么今天小编跟您聊一聊,您的企业 ...
- 如何更好理解Peterson算法?
如何更好理解Peterson算法? 1 Peterson算法提出的背景 在我们讲述Peterson算法之间,我们先了解一下Peterson算法提出前的背景(即:在这个算法提出之前,前人们都做了哪些工作 ...
- traefik: 基础入门总结
traefik介绍 traefik-现代反向代理,也可称为现代边缘路由:traefik原声兼容主流集群,Kubernetes,Docker,AWS等.官方的定位traefik是一个让开发人员将时间花费 ...
- [DB] MapReduce
概述 大数据计算的核心思想:移动计算比移动数据更划算 MapReduce既是一个编程模型,又是一个计算框架 包含Map和Reduce两个过程 终极目标:用SQL语句分析大数据(Hive.SparkSQ ...
- 【python】读取和输出到txt
读取txt的数据和把数据保存到txt中是经常要用到的,下面我就总结一下. 读txt文件python常用的读取文件函数有三种read().readline().readlines() 以读取上述txt为 ...