使用栈来完成一个表达式的结果

原文地址:传送门

使用栈来完成一个表达式的结果

使用栈完成计算 一个表达式的结果

7*2*2-5+1-5+3-4 = ?
3+2*6-2

哔哩哔哩动画

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XzPnJzRe-1614845779689)(https://victorfengming.gitee.io/data_algorithm/img/QQ%E6%88%AA%E5%9B%BE20210220134231.png)]

使用栈完成表达式的计算 思路

  1. 通过一个 index 值(索引),来遍历我们的表达式
  2. 如果我们发现是一个数字, 就直接入数栈
  3. 如果发现扫描到是一个符号, 就分如下情况
    • 3.1 如果发现当前的符号栈为 空,就直接入栈
    • 3.2 如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符 就需要从数栈中pop出两个数,在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈, 如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.
  4. 当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.
  5. 最后在数栈只有一个数字,就是表达式的结果

验证: 3+2*6-2 = 13

一位数运算

计算

package com.atguigu.stack;/*** ClassName:  <br/>* Description:  <br/>* Date: 2021-02-20 14:02 <br/>* @project data_algorithm* @package com.atguigu.stack*/
public class Calculator {}//先创建一个栈,直接使用前面创建好
//定义一个 ArrayStack2 表示栈, 需要扩展功能
class ArrayStack2 {private int maxSize; // 栈的大小private int[] stack; // 数组,数组模拟栈,数据就放在该数组private int top = -1;// top表示栈顶,初始化为-1//构造器public ArrayStack2(int maxSize) {this.maxSize = maxSize;stack = new int[this.maxSize];}//增加一个方法,可以返回当前栈顶的值, 但是不是真正的poppublic int peek() {return stack[top];}//栈满public boolean isFull() {return top == maxSize - 1;}//栈空public boolean isEmpty() {return top == -1;}//入栈-pushpublic void push(int value) {//先判断栈是否满if(isFull()) {System.out.println("栈满");return;}top++;stack[top] = value;}//出栈-pop, 将栈顶的数据返回public int pop() {//先判断栈是否空if(isEmpty()) {//抛出异常throw new RuntimeException("栈空,没有数据~");}int value = stack[top];top--;return value;}//显示栈的情况[遍历栈], 遍历时,需要从栈顶开始显示数据public void list() {if(isEmpty()) {System.out.println("栈空,没有数据~~");return;}//需要从栈顶开始显示数据for(int i = top; i >= 0 ; i--) {System.out.printf("stack[%d]=%d\n", i, stack[i]);}}//返回运算符的优先级,优先级是程序员来确定, 优先级使用数字表示//数字越大,则优先级就越高.public int priority(int oper) {if(oper == '*' || oper == '/'){return 1;} else if (oper == '+' || oper == '-') {return 0;} else {return -1; // 假定目前的表达式只有 +, - , * , /}}//判断是不是一个运算符public boolean isOper(char val) {return val == '+' || val == '-' || val == '*' || val == '/';}//计算方法public int cal(int num1, int num2, int oper) {int res = 0; // res 用于存放计算的结果switch (oper) {case '+':res = num1 + num2;break;case '-':res = num2 - num1;// 注意顺序break;case '*':res = num1 * num2;break;case '/':res = num2 / num1;break;default:break;}return res;}}

启动

    public static void main(String[] args) {//根据前面老师思路,完成表达式的运算String expression = "7*2*2-5+1-5+3-4"; // 15//如何处理多位数的问题?//创建两个栈,数栈,一个符号栈ArrayStack2 numStack = new ArrayStack2(10);ArrayStack2 operStack = new ArrayStack2(10);//定义需要的相关变量int index = 0;//用于扫描int num1 = 0; int num2 = 0;int oper = 0;int res = 0;char ch = ' '; //将每次扫描得到char保存到chString keepNum = ""; //用于拼接 多位数//开始while循环的扫描expressionwhile(true) {//依次得到expression 的每一个字符ch = expression.substring(index, index+1).charAt(0);//判断ch是什么,然后做相应的处理if(operStack.isOper(ch)) {//如果是运算符//判断当前的符号栈是否为空if(!operStack.isEmpty()) {//如果符号栈有操作符,就进行比较,如果当前的操作符的优先级小于或者等于栈中的操作符,就需要从数栈中pop出两个数,//在从符号栈中pop出一个符号,进行运算,将得到结果,入数栈,然后将当前的操作符入符号栈if(operStack.priority(ch) <= operStack.priority(operStack.peek())) {num1 = numStack.pop();num2 = numStack.pop();oper = operStack.pop();res = numStack.cal(num1, num2, oper);//把运算的结果如数栈numStack.push(res);//然后将当前的操作符入符号栈operStack.push(ch);} else {//如果当前的操作符的优先级大于栈中的操作符, 就直接入符号栈.operStack.push(ch);}}else {//如果为空直接入符号栈..operStack.push(ch); // 1 + 3}} else { //如果是数,则直接入数栈//numStack.push(ch - 48); //? "1+3" '1' => 1//分析思路//1. 当处理多位数时,不能发现是一个数就立即入栈,因为他可能是多位数//2. 在处理数,需要向expression的表达式的index 后再看一位,如果是数就进行扫描,如果是符号才入栈//3. 因此我们需要定义一个变量 字符串,用于拼接//处理多位数keepNum += ch;//如果ch已经是expression的最后一位,就直接入栈if (index == expression.length() - 1) {numStack.push(Integer.parseInt(keepNum));}else{//判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符,则入栈//注意是看后一位,不是index++if (operStack.isOper(expression.substring(index+1,index+2).charAt(0))) {//如果后一位是运算符,则入栈 keepNum = "1" 或者 "123"numStack.push(Integer.parseInt(keepNum));//重要的!!!!!!, keepNum清空keepNum = "";}}}//让index + 1, 并判断是否扫描到expression最后.index++;if (index >= expression.length()) {break;}}//当表达式扫描完毕,就顺序的从 数栈和符号栈中pop出相应的数和符号,并运行.while(true) {//如果符号栈为空,则计算到最后的结果, 数栈中只有一个数字【结果】if(operStack.isEmpty()) {break;}num1 = numStack.pop();num2 = numStack.pop();oper = operStack.pop();res = numStack.cal(num1, num2, oper);numStack.push(res);//入栈}//将数栈的最后数,pop出,就是结果int res2 = numStack.pop();System.out.printf("表达式 %s = %d", expression, res2);}

原文地址:传送门

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

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

相关文章

Python 关于bytes类方法对数字转换的误区, Json的重要性

本文起源于一次犯错, 在发觉bytes()里面可以填数字, 转出来的也是bytes类型, 就心急把里面的东西decode出来. 结果为空.搞来搞去以为是命令不熟练事实上错在逻辑.a1 bytes(11, encodingutf-8) print(a1)b1 a1.decode()print(b1)a2 bytes(11) print(a2)b2 a2.decode() print…

psnr 计算

PSNR是“Peak Signal to Noise Ratio”的缩写&#xff0c;峰值信噪比。psnr一般是用于最大值信号和背景噪音之间的一个工程项目。 PSNR计算公式如下&#xff1a; 8bits表示法中&#xff0c;peak的最大值为255&#xff1b;MSE指Mean Square Error&#xff08;均方误差&#xff0…

光源时间_缩短背光源的使用寿命的原因

许多场所都会使用到led这种产品&#xff0c;这种产品经常用于背光的照亮中。但是由于使用led的局限性较大&#xff0c;所以led逐渐被背光源这种产品所代替&#xff0c;常常用于背景的照亮让宣传图可以展现出更好的视觉&#xff0c;这也是许多人选择背光源的原因。那么&#xff…

递归应用场景和调用机制

原文链接:传送门 递归 迷宫问题(回溯) 概念 简单呐的说: 递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,同时让代码变得简洁. 案例-递归调用机制 打印问题 public static void test(int n){if(n>2){test(n-1);}System.out.print…

八皇后问题分析与Java实现

原文链接:传送门 八皇后问题 八皇后问题&#xff0c;是一个古老而著名的问题&#xff0c;是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯贝瑟尔于1848年提出&#xff1a;在88格的国际象棋上摆放八个皇后&#xff0c;使其不能互相攻击&#xff0c;即&#xff1a;任意两个…

单例模式之恶汉模式(详解)

一.设计模式 概念&#xff1a;设计模式是一套被反复使用、多人知晓的、经过分类编目的、代码设计经验的总结。 目的&#xff1a;是用设计模式可以重用代码&#xff0c;让代码更容易被他人理解&#xff0c;保证代码的可靠性。 二.为什么要使用单例模式&#xff1f; 如果创造出多…

迷宫回溯问题分析和实现

原文链接:传送门 迷宫问题 说明: 小球得到的路径&#xff0c;和程序员设置的找路策略有关即&#xff1a;找路的上下左右的顺序相关再得到小球路径时&#xff0c;可以先使用(下右上左)&#xff0c;再改成(上右下左)&#xff0c;看看路径是不是有变化测试回溯现象思考: 如何求出…

canvas clear 指定属性的元素_好程序员web前端分享CSS属性组成及作用

好程序员web前端分享CSS属性组成及作用学习目标1、css属性和属性值的定义2、css文本属性3、css列表属性4、css背景属性5、css边框属性6、css浮动属性一、css属性和属性值的定义属性&#xff1a;属性是指定选择符所具有的属性&#xff0c;它是css的核心&#xff0c;css2共有150多…

排序算法介绍和分类

原文链接:传送门 排序算法的介绍 排序也成排序算法 排序也称排序算法(Sort Algorithm)&#xff0c;排序是将一组数据&#xff0c;依指定的顺序进行排列的过程。 排序的分类&#xff1a; 1) 内部排序: 指将需要处理的所有数据都加载到**内部存储器(内存)**中进行排序。 2) 外…

认识高清视频编码(MPEG、H.264、WMV-HD、RMVB)

文章出处&#xff1a;www.net1980.com 原创 最近两年&#xff0c;“高清”这个词语非常火热&#xff0c;已经成为家电和IT行业的最新潮流了。高清视频和普通视频有什么区别呢&#xff1f;主要是分辨率上的区别&#xff0c;720P视频的分辨率为1280X720&#xff0c;1080P视频的分…

解读SPP / SPPF / SimSPPF / ASPP / RFB / SPPCSPC

SPP与SPPF 一、SPP的应用的背景 在卷积神经网络中我们经常看到固定输入的设计&#xff0c;但是如果我们输入的不能是固定尺寸的该怎么办呢&#xff1f; 通常来说&#xff0c;我们有以下几种方法&#xff1a; &#xff08;1&#xff09;对输入进行resize操作&#xff0c;让他们…

go mongodb排序查询_《MongoDB》day two

Mongodb的更新方式有&#xff1f;db.集合名.update() 函数:用于更新已存在的文档。语法格式&#xff1a;db.COLLECTION_NAME.update({查询条件},{更新内容},{更新参数(可选)}) 注&#xff1a;这种方式会覆盖原有的文档。使用更新操作符 使用 save()函数更新文档 Mongodb的updat…

哈希表思路图解和代码实现

原文链接传送门 哈希表(散列)-Google上机题 看一个实际需求&#xff0c;google公司的一个上机题: 有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址…),当输入该员工的id时,要求查找到该员工的 所有信息. 要求: 不使用数据库,尽量节省内存,速度越…

glibc交叉编译_TSN之linuxptp交叉编译

0 开发环境1 linuxptp是什么2 为什么要交叉编译linuxptp3 修改makefile4 修改源码5 交叉编译0 开发环境笔记本&#xff1a;ubuntu18.04.5&#xff0c;内核版本为5.3 开发板&#xff1a;imx8mp-evk内核版本&#xff1a;Linux5.4.24交叉编译工具链&#xff1a;fsl-imx-xwayland-g…

声音编码

1.脉冲编码调制PCM文件格式简介 将音频数字化&#xff0c;其实就是将声音数字化。最常见的方式是透过脉冲编码调制PCM(Pulse Code Modulation) 。运作原理如下。首先我们考虑声音经过麦克风&#xff0c;转换成一连串电压变化的信号&#xff0c;如图一所示。这张图的横座标为秒&…

Elastic Stack简介

Elastic Stack简介 如果你没有听说过Elastic Stack&#xff0c;那你一定听说过ELK&#xff0c;实际上ELK是三款软件的简称&#xff0c;分别是Elasticsearch、 Logstash、Kibana组成&#xff0c;在发展的过程中&#xff0c;又有新成员Beats的加入&#xff0c;所以就形成了Elast…

webpack v3 结合 react-router v4 做 dynamic import — 按需加载(懒加载)

为什么要做dynamic import&#xff1f; dynamic import不知道为什么有很多叫法&#xff0c;什么按需加载&#xff0c;懒加载&#xff0c;Code Splitting&#xff0c;代码分页等。总之&#xff0c;就是在SPA&#xff0c;把JS代码分成N个页面份数的文件&#xff0c;不在用户刚进来…

go kegg_工具篇丨GO和KEGG富集不到通路?快试试这个超赞的功能分析工具吧

GO和KEGG富集分析是我们在筛选出差异表达基因之后&#xff0c;都会去做的套路性分析。然鹅……我相信&#xff0c;总有那么一些“倒霉孩子”会遇到跟我一样的窘境吧&#xff0c;好不容易筛选出来的差异基因&#xff0c;尝试了DAVID(https://david.ncifcrf.gov/)、Metascape(htt…

搭建Telnet服务器

搭建Telnet服务器 作者&#xff1a;尹正杰 版权声明&#xff1a;原创作品&#xff0c;谢绝转载&#xff01;否则将追究法律责任。 可能大家都知道现在已经很少有人用TELNET服务器&#xff0c; 因为它传输数据是以明文的方式&#xff0c;我们很容易通过抓包软件讲数据进行抓包&a…

table取tr对象 vue_Vue笔记

Vue集成了React和Angular的优点&#xff0c;摒弃了他们的缺点。Vue的官网&#xff1a;https://cn.vuejs.org/v2/api/Vue诞生于2016年&#xff0c;是现在非常流行的MVVM框架。Vue提供了“引包”的使用方法&#xff0c;初学者可以在这之下学习语法。不需要webpack&#xff0c;不需…