数据结构之栈实现中缀转后缀并计算结果

一.中缀变后缀过程分析

给定一个中缀,最后变为后缀的过程其实并不算复杂,下面分析一下过程:

1. 首先面对一个中缀表达式,我们需要两个栈,一个用来存放运算符,即符号栈 operatorstack,一个用来存放数字,运算符,即数字栈 numStack

2. 开始扫描中缀表达式

3.遇到操作数时,我们直接压入数字栈,即numStack;

4.遇到运算符时,需要我们比较一下当前符号与栈顶符号的优先级,这里分以下三种情况

  4.1 operatorStack为空,好的,我们直接压入

  4.2 operatorStack不为空,且当前符号的优先级大于栈顶符号的优先级,我们也直接压入符号栈

  4.3 operatorStack不为空,且当前符号的优先级小于或者等于栈顶符号的优先级,这是我们需要先将operatorStack的栈顶pop出并push到numStack,此处是一个while循环,直到找出当前符号的优先级大于符号栈栈顶符    号的优先级为止,再将当前符号压入operatorStack.

5.遇到括号时,有如下操作

  5.1 如果是  "("  ,直接压入符号栈.operatorStack;

  5.2 如果是  ")"  ,则将符号栈栈内符号依次弹出,push进numStack,直到遇见  "("  为止,注意的是,这一对括号进入丢弃状态,即  "(" 弹出,不会入任何栈,")" 也不会入任何栈

6.重复2-5,扫描中缀表达式,直到最后结束

7.最后将符号栈中符号顺序弹出并加入数字栈

8.数字栈numStack输出,结果的逆序就是我们要的后缀表达式

二. 代码实现

通过一中的过程分析我们可以看到,数字栈从头到输出之前并没有进行任何弹栈操作,所以为了便于书写,下面将数字栈采用arrayList来代替,且易于输出

并且,如果采用索引去对中队表达式进行扫描的话,会十分麻烦,所以我们采用以下思路,进行转换并计算结果

中缀表达式 -->顺序存放中缀表达式中数字,操作符以及括号的list集合 --> 根据上面一的思路转成存放后缀表达式的元素的集合 rearList-->遍历rearList进行计算

代码如下:

package com.ebiz.stack;import java.util.ArrayList;
import java.util.List;
import java.util.Stack;/*** @author YHj* @create 2019-07-24 15:51** 中缀表达式转后缀表达式*/
public class MiddleToRear {public static void main(String[] args) {//不用索引扫描表达式,将表达式加入到list中String expression="1+((2+3)*4)-5";//得到中缀表达式转为list的集合List<String> list=getList(expression);//将中缀表达式的集合转到后缀表达式的集合List<String> rearList=getRearList(list);System.out.println("rearList = " + rearList);//输出计算结果
        System.out.println(getResult(rearList));}//中缀表达式的集合转为后缀表达式的集合private static List<String> getRearList(List<String> list) {ArrayList<String> rearList = new ArrayList<>();//定义符号栈Stack<String> operatorStack = new Stack<>();//定义集合代替数字栈,数字栈本身并没有pop操作,并且最后要倒叙输出,随意用list代替ArrayList<String> numList = new ArrayList<>();for (String s : list) {//如果是个数字if (s.matches("\\d+")){numList.add(s);}else if (s.equals("(")){operatorStack.push(s);}else if (s.equals(")")){//符号栈栈顶直到左括号之前的符号放入数字栈while (!"(".equals(operatorStack.peek())){numList.add(operatorStack.pop());}//把左括号弹出来
                operatorStack.pop();//判断优先级,当前符号优先级小于等于符号栈栈顶优先级,将符号栈栈顶弹出加入数字栈,//直到找到当前符号优先级大于符号栈栈顶优先级为止,再将当前符号加入符号栈}else{while (operatorStack.size()!=0 && (OperPriority.getPriority(s) <= OperPriority.getPriority(operatorStack.peek()))){numList.add(operatorStack.pop());}//将当前符号加入符号栈
                operatorStack.push(s);}}//将符号栈中剩余符号加入数字栈while (operatorStack.size()!=0){numList.add(operatorStack.pop());}return numList;}//将中缀表达式的各个字符存到list集合,方面遍历private static List<String> getList(String expression) {ArrayList<String> list = new ArrayList<>();int index=0;String str=""; //多位数的拼接char c;  //用于存放每次扫描到的结果do {//判断是否为数字,非数字直接加入listc=expression.charAt(index);if (c < 48 || c >57){list.add(""+c);}else {//数字.考虑可能不是一位数,字符串拼接str+=c;if (index == expression.length()-1){list.add(str);}else {if (expression.charAt(index+1) < 48 || expression.charAt(index+1) > 57){list.add(str);str="";}}}index++;}while (index < expression.length());return list;}//输出计算结果private static int getResult(List<String> list) {Stack<String> stack = new Stack<>();for (String s : list) {//匹配数字if (s.matches("\\d+")){stack.push(s);}else {int num01=Integer.parseInt(stack.pop());int num02=Integer.parseInt(stack.pop());int result=0;if (s.equals("+")){result=num01+num02;}else if (s.equals("-")){result=num02-num01;}else if (s.equals("*")){result=num02*num01;}else if (s.equals("/")){result=num02/num01;}else {throw new RuntimeException("无法解析的字符串");}stack.push(""+result);}}return Integer.parseInt(stack.pop());}}

 上面涉及到的判断符号优先级的类

package com.ebiz.stack;/*** @author YHj* @create 2019-07-24 18:14*/
public class OperPriority {private static int AAD =1; //加;private static int SUB =1; //private static int MUL =2; //private static int DIV =2; //public static int getPriority(String operator){int result=0;switch (operator){case "+":result=AAD;break;case "-":result=SUB;break;case "*":result=MUL;break;case "/":result=DIV;break;default:break;}return result;}}

 

有待完善...

转载于:https://www.cnblogs.com/jiushixihuandaqingtian/p/11241370.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/410455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TreeView 小技巧

1、在把treeview的check事件给封了之后&#xff0c;在双击的情况下仍然会选中。这个要通过处理消息来解决。 解决&#xff1a; 在调用的时候将这个事件给过滤掉 if (e.Node.ForeColor Color.Gray) e.Cancel true; 自定义treeview中加入以下方法 protected ove…

python爬取新闻网站内容_python爬虫案例:抓取网易新闻

此文属于入门级级别的爬虫&#xff0c;老司机们就不用看了。 本次主要是爬取网易新闻&#xff0c;包括新闻标题、作者、来源、发布时间、新闻正文。 首先我们打开163的网站&#xff0c;我们随意选择一个分类&#xff0c;这里我选的分类是国内新闻。然后鼠标右键点击查看源代码&…

PHPRedis教程之geo

前言 支持 GEO 系列命令的 Redis 版本从 3.2.0 起开始才可以使用&#xff0c;所以之前版本就不要想了。 函数列表 geoadd - 将指定的地理空间项&#xff08;纬度&#xff0c;经度&#xff0c;名称&#xff09;添加到指定的键&#xff0c; 数据作为有序集存储在 Redis 中。 GEOA…

如何查看QQ和微信查看授权过那些应用?

平时生活中&#xff0c;要登录一些网站或者app时&#xff0c;为了省事儿&#xff0c;都用第三方登录&#xff0c;登录是简单快捷了一些 时间长了,授权过的那些应用都不知道了&#xff0c;甚至一些应用你没用去授权权限也一直开放给别人网站的 所以为了自己帐号的安全还是有必…

[html] 说说你对H5的SharedWorker的理解,它有什么运用场景?

[html] 说说你对H5的SharedWorker的理解&#xff0c;它有什么运用场景&#xff1f; 一种特定类型的 worker&#xff0c;可以从几个浏览上下文中访问&#xff0c;例如几个窗口、iframe 或其他 worker。多个标签页之间通信个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后…

Spring 注解AOP 入门

XML <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xmlns:context"http://www.springframework.org/sche…

python常用函数的用法_python3 文件操作常用函数用法示例

1. file.close() 关闭文件。关闭后文件不能再进行读写操作&#xff0c;需要重新打开才能进行读写。f open(demo.text , r) # 使用只读方式打开文本 print(f.read()) # 打印demo.text文件内容 f.close() # 关闭文件 2. file.flush() 将缓存区中的数据立刻写入文件&#xff0c;同…

[html] 制作页面时,前端如何适应各种异形屏?

[html] 制作页面时&#xff0c;前端如何适应各种异形屏&#xff1f; 主要内容区域大小固定&#xff0c;固定在页面中间&#xff0c;两边可伸缩 width:1200px; margin:0 auto;个人简介 我是歌谣&#xff0c;欢迎和大家一起交流前后端知识。放弃很容易&#xff0c; 但坚持一定很…

awk的妙用

终端形式有人说awk的优势在于可以个性化输出命令&#xff0c;这么说来太抽象了&#xff0c;假如我们查看占用6379端口的进程信息。 lsof -i:6379 输出结果&#xff1a; COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME redis-ser 17474 root 6u IPv6 71242 …

追求真实

是选择在迷茫中生活然后死去 还是选择追求真实&#xff0c;在追求的路上死去。 两种方式共同点是死去的时候都是迷茫的。不得不说是生命的悲剧&#xff0c;不过也可以说是生命的精彩转载于:https://www.cnblogs.com/cuihongyu3503319/archive/2011/08/07/2130204.html

C# ASP.NET MVC 图片上传的多种方式(存储至服务器文件夹,阿里云oss)

图片上传时我们进场用到的一个功能今天将他整理了一下写了个demo希望对大家有用 该demo分为如下 1.上传至至服务器文件夹 2.上传至阿里云oss 3.百度webupload上传图片 效果图如下: 首先讲解一下后台代码 (1)上传至服务器存储 using System; using System.Collections; u…

[html] 写一个布局,当页面滚动一定高时,导航始终固定在顶部,反之恢复原位

[html] 写一个布局&#xff0c;当页面滚动一定高时&#xff0c;导航始终固定在顶部&#xff0c;反之恢复原位 使用粘性定位&#xff0c;position:sticky 记得使用的时候父元素不能使用overflow:hidden和overflow:auto属性&#xff0c;而且必须要指定top/left/bottom/right中任…

java变量命名规则_浅谈JAVA开发规范与开发细节(上)

开发团队在开发过程中&#xff0c;由于每个人的开发习惯&#xff0c;以及对于技术的理解深浅程度不一&#xff0c;往往一个项目在开发过程中&#xff0c;代码的质量&#xff0c;代码的风格都不尽相似&#xff0c;所以有一份适合团队的代码规范是非常有必要的&#xff0c;而一个…

使用Moles对静态方法做UnitTest

我们在开发&#xff0c;有时遇到一些Legcy代码&#xff0c;然后需要对它们进行UnitTest。UnitTest的重要性在这里不再说了。但是发现某些Class中有些方法是Static的&#xff0c;按以往的方法我们需要用Extact Interface 方法 从那个需要测试的Class&#xff0c;然后使用 IOC /D…

Charles

安装 https://www.jianshu.com/p/cb744a4c0344 https://blog.csdn.net/qq_28831197/article/details/81196571 使用说明&#xff1a; 来源&#xff1a;https://www.jianshu.com/p/73b134559c76 过滤网络请求 通常情况下&#xff0c;我们需要对网络请求进行过滤&#xff0c;只监…

.NET Core Docker使用初入篇

本篇内容如何在CentOS上安装Docker服务器与工具准备安装Docker更新系统安装Docker源设置Docker开机启动启动Docker使用Docker运行一个.NET Core 例子.net core 例子拉取.net core 例子停止.net core 例子启用其他如何在CentOS上安装Docker 服务器与工具准备 首先我们需要一个…

[html] 写一个布局,当页面滚动一定高时,导航始终固定在顶部,反之恢复原位

[html] 写一个布局&#xff0c;当页面滚动一定高时&#xff0c;导航始终固定在顶部&#xff0c;反之恢复原位 使用粘性定位&#xff0c;position:sticky 记得使用的时候父元素不能使用overflow:hidden和overflow:auto属性&#xff0c;而且必须要指定top/left/bottom/right中任…

C++学习记录

1.C中没有C#中所谓的引用类型和值类型&#xff0c;需要使用引用&#xff0c;或者指针操作对象&#xff0c;但是指针容易出错&#xff0c;为什么不用引用而用指针呢&#xff0c;下面给出总结 <1>引用在声明时必须初始化&#xff0c;指针可以是空指针&#xff0c;引用定义后…

如何延长作用域链_第4部分2:作用域(链)和 闭包

知识列表作用域/作用域链 闭包&#xff08;涉及JS垃圾回收机制 &#xff09;https://zhuanlan.zhihu.com/p/27110726 【 js 基础 】【读书笔记】作用域和闭包https://juejin.im/post/5afb0ae56fb9a07aa2138425 深入理解闭包之前置知识→作用域与词法作用域&#xff08;一&#…

nginx配置简介

一、安装部署环境&#xff1a;centos 7.21.离线安装&#xff1a;Nginx下载地址&#xff1a;http://nginx.org/en/download.html下载稳定版本nginx-1.16.0.tar.gz到/usr/local下进行解压安装&#xff1a; # ./configure --prefix/usr/local/nginx-1.16.0 --with-pcre \ # make &…