【数据结构】使用栈实现综合计算器

 首先初始化两个栈,数栈(numStack)用于存放数据符号栈(operStack)用于存放运算符

计算思路

1.通过一个index值(索引)来遍历表达式

2.如果发现扫描到一个数字,就直接入数栈

3.如果发现扫描到一个符号,就分如下情况

①如果当前符号栈为空,就直接入符号栈

②如果符号栈有操作符,就进行比较,如果当前操作符的优先级小于或者等于栈中的操作符,就需要从数栈中 pop 出两个数进行运算,运算结果入数栈,然后将当前操作符入符号栈;如果当前操作符的优先级大于栈中的的操作符,就直接入符号栈

4.当表达式扫描完毕,就顺序的从数栈和符号栈中pop出相应的数和符号,并运算

5.最后数栈中只有一个数字,就是表达式的结果

判断运算符优先级

//返回运算符的优先级,优先级由程序员来确定,优先级使用数字表示
//数字越大优先级越高
public int priority(int oper) {if (oper == '+' || oper == '-') {return 0;} else if (oper == '*' || oper == '/') {return 1;} else {return -1;  //假定目前的表达式只有+,-,*,/}
}

判断是否为运算符

public boolean isOper(char val) {return val == '+' || val == '-' || val == '*' || val == '/';
}

进行运算

public int cal(int num1, int num2, char 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 class Calculator {public static void main(String[] args) {String expression = "7+2*6-4";//创建两个栈,数栈,符号栈ArrayStack2 numStack = new ArrayStack2(10);ArrayStack2 operStack = new ArrayStack2(10);//定义需要的相关变量int index = 0;int num1;int num2;int oper;int res;char ch;  //将每次扫描得到的char保存到ch//开始while循环扫描expressionwhile (true) {//依次得到 expression 中的每个字符ch = expression.charAt(index);//判断ch是什么,然后做相应的处理if (operStack.isOper(ch)) {  //如果是运算符//判断当前的符号栈是否为空if (!operStack.isEmpty()) {/*如果符号栈有操作符,就进行比较,如果当前操作符的优先级小于或者等于栈中的操作符,就需要从数栈中 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 {numStack.push(ch -'0');}//让 index++ ,并判断是否扫描到 expression 最后index++;if (index == expression.length()) {break;}}//当表达式扫描完毕,就顺序的从数栈和符号栈中 pop 出相应的数和符号,并运行while (!operStack.isEmpty()) {num1 = numStack.pop();num2 = numStack.pop();oper = operStack.pop();res = numStack.cal(num1, num2, oper);numStack.push(res);  //入栈}System.out.printf("表达式%s = %d", expression, numStack.pop());}
}//先创建一个栈
//定义一个 ArrayStack 表示栈
class ArrayStack2 {private int maxSize;  //栈的大小private int[] stack;  //数组,数组模拟栈,数据就放在该数组private int top = -1;  //top 表示栈顶,初始化为 -1//构造器public ArrayStack2(int maxSize) {this.maxSize = maxSize;stack = new int[maxSize];}//栈满public boolean isFull() {return top == maxSize - 1;}//栈空public boolean isEmpty() {return top == -1;}//入栈 - pushpublic void push(int value) {//先判断栈是否满if (isFull()) {System.out.println("栈已满,不能添加数据");return;}stack[++top] = value;}//出栈 - poppublic int pop() {//先判断栈是否空if (isEmpty()) {//抛出异常throw new RuntimeException("栈为空,不能取出数据");}int value = stack[top];top--;return value;}//返回栈顶数据,但不出栈 - peekpublic int peek() {return stack[top];}//显示栈的情况(遍历栈),遍历时,需要从栈顶开始显示数据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 0;} else if (oper == '*' || oper == '/') {return 1;} 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 class Calculator {public static void main(String[] args) {String expression = "70+20*6-4";//创建两个栈,数栈,符号栈ArrayStack2 numStack = new ArrayStack2(10);ArrayStack2 operStack = new ArrayStack2(10);//定义需要的相关变量int index = 0;int num1;int num2;int oper;int res;char ch;  //将每次扫描得到的char保存到chString keepNum = "";//开始while循环扫描expressionwhile (true) {//依次得到 expression 中的每个字符ch = expression.charAt(index);//判断ch是什么,然后做相应的处理if (operStack.isOper(ch)) {  //如果是运算符//判断当前的符号栈是否为空if (!operStack.isEmpty()) {/*如果符号栈有操作符,就进行比较,如果当前操作符的优先级小于或者等于栈中的操作符,就需要从数栈中 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 {  //如果是数,则直接入数栈/*分析思路1.当处理多位数时,不能发现是一个数就立即入栈,因为可能是多位数2.向 expression 的表达式的 index 后再看一位,如果是数就进行扫描,如果是符号才入栈3.因此定义一个字符串变量用于拼接*///处理多位数keepNum += ch;//如果 ch 已经是 expression 的最后一位,就直接入栈if (index == expression.length() - 1) {numStack.push(Integer.parseInt(keepNum));} else {//判断下一个字符是不是数字,如果是数字,就继续扫描,如果是运算符则入栈if (operStack.isOper(expression.substring(index + 1,index + 2).charAt(0))) {//如果最后一位是运算符,则入栈 keepNum = "1" 或者 "123"numStack.push(Integer.parseInt(keepNum));//重要的!!!keepNum 清空keepNum = "";}}}//让 index++ ,并判断是否扫描到 expression 最后index++;if (index == expression.length()) {break;}}//当表达式扫描完毕,就顺序的从数栈和符号栈中 pop 出相应的数和符号,并运行while (!operStack.isEmpty()) {num1 = numStack.pop();num2 = numStack.pop();oper = operStack.pop();res = numStack.cal(num1, num2, oper);numStack.push(res);  //入栈}System.out.printf("表达式%s = %d", expression, numStack.pop());}
}//先创建一个栈
//定义一个 ArrayStack 表示栈
class ArrayStack2 {private int maxSize;  //栈的大小private int[] stack;  //数组,数组模拟栈,数据就放在该数组private int top = -1;  //top 表示栈顶,初始化为 -1//构造器public ArrayStack2(int maxSize) {this.maxSize = maxSize;stack = new int[maxSize];}//栈满public boolean isFull() {return top == maxSize - 1;}//栈空public boolean isEmpty() {return top == -1;}//入栈 - pushpublic void push(int value) {//先判断栈是否满if (isFull()) {System.out.println("栈已满,不能添加数据");return;}stack[++top] = value;}//出栈 - poppublic int pop() {//先判断栈是否空if (isEmpty()) {//抛出异常throw new RuntimeException("栈为空,不能取出数据");}int value = stack[top];top--;return value;}//返回栈顶数据,但不出栈 - peekpublic int peek() {return stack[top];}//显示栈的情况(遍历栈),遍历时,需要从栈顶开始显示数据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 0;} else if (oper == '*' || oper == '/') {return 1;} 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;}
}

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

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

相关文章

Python | TypeError: ‘function’ object is not subscriptable

Python | TypeError: ‘function’ object is not subscriptable 在Python编程中&#xff0c;遇到“TypeError: ‘function’ object is not subscriptable”这一错误通常意味着你尝试像访问列表、元组、字典或字符串等可订阅&#xff08;subscriptable&#xff09;对象那样去…

Javascript面试基础6(下)

获取页面所有checkbox 怎样添加、移除、移动、复制、创建和查找节点 在JavaScript中&#xff0c;操作DOM&#xff08;文档对象模型&#xff09;是常见的任务&#xff0c;包括添加、移除、移动、复制、创建和查找节点。以下是一些基本的示例&#xff0c;说明如何执行这些操作&a…

Java语言程序设计——篇九(2)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; 枚举类型 枚举类型的定义枚举类型的方法实战演练 枚举在switch中的应用实战演练 枚举类的构造方法实战演练 枚举类型的定义 [修饰符] enum 枚举…

医院影像平台源码,C/S体系结构的C#语言PACS系统全套商业源代码

医学学影像临床信息系统具有图像采集、显示、存储、传输和管理等功能&#xff0c;支持DICOM影像设备和非DICOM影像设备&#xff0c;可以识别CT、MR、CR/DR、X光、DSA、B超、NM、SC等设备的图像类型&#xff0c;可对数字影像进行无损压缩和有损压缩处理。C/S体系结构的多媒体数据…

湖仓一体架构解析:数仓架构选择(第48天)

系列文章目录 1、Lambda 架构 2、Kappa 架构 3、混合架构 4、架构选择 5、实时数仓现状 6、湖仓一体架构 7、流批一体架构 文章目录 系列文章目录前言1、Lambda 架构2、Kappa 架构3、混合架构4、架构选择5、实时数仓现状6、湖仓一体架构7、流批一体架构 前言 本文解析了Lambd…

Verilog语言和C语言的本质区别是什么?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C语言的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 用老石的一句话其实很好说…

ssm框架整合,异常处理器和拦截器(纯注解开发)

目录 ssm框架整合 第一步&#xff1a;指定打包方式和导入所需要的依赖 打包方法&#xff1a;war springMVC所需依赖 解析json依赖 mybatis依赖 数据库驱动依赖 druid数据源依赖 junit依赖 第二步&#xff1a;导入tomcat插件 第三步&#xff1a;编写配置类 SpringCon…

【AI绘画】Midjourney V6初学者完全指南 参数篇

本文我们将详细介绍对图像生成结果产生重大影响的"参数"。 1. 什么是参数? 参数是一种添加到提示末尾以调整图像生成输出设置的方法。 它们用两个连字符"–“和特定字符串表示,如”–ar"、“–chaos”、"–r"等。 您也可以同时使用多个参数…

java项目中添加SDK项目作为依赖使用(无需上传Maven)

需求&#xff1a; 当需要多次调用某个函数或算法时&#xff0c;不想每次调用接口都自己编写&#xff0c;可以将该项目打包&#xff0c;以添加依赖的方式实现调用 适用于&#xff1a; 无需上线的项目&#xff0c;仅公司或团队内部使用的项目 操作步骤&#xff1a; 以下面这…

菜鸟从0学微服务——MyBatis-Plus

关于“菜鸟从0学微服务” 针对有编程基础&#xff0c;开始学习微服务的同学&#xff0c;我们陆续推出从0学微服务的笔记分享。力求从各个中间件的使用来反思这些中间件的作用和优势。 会分享的比较快&#xff0c;会记录demo演算和中间件的使用过程&#xff0c;至于细节的理论…

【数学建模】——【python】实现【最短路径】【最小生成树】【复杂网络分析】

目录 1. 最短路径问题 - 绘制城市间旅行最短路径图 题目描述&#xff1a; 要求&#xff1a; 示例数据&#xff1a; python 代码实现 实现思想&#xff1a; 要点&#xff1a; 2. 最小生成树问题 - Kruskal算法绘制MST 题目描述&#xff1a; 要求&#xff1a; 示例数据…

PostgreSQL入门与进阶学习,体系化的SQL知识,完成终极目标高可用与容灾,性能优化与架构设计,以及安全策略

​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 概述基础篇初级篇进阶篇…

事务、函数和索引

目录 什么是事务&#xff1f; 事务的ACID原则&#xff1a; 事务的操作 事务的原子性、一致性、持久性 事务的隔离性 什么是事务的隔离性? 用什么方法实现事务的隔离性&#xff1f; MySQL中的锁 锁分类&#xff1a; 事务的隔离级别 事务并发问题 InnoDB的MVCC MVCC…

【C++】红黑树的应用(封装map和set)

✨ 青山一道同云雨&#xff0c;明月何曾是两乡 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;C学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &…

Unity UGUI 实战学习笔记(3)

仅作学习&#xff0c;不做任何商业用途 不是源码&#xff0c;不是源码! 是我通过"照虎画猫"写的&#xff0c;可能有些小修改 不提供素材&#xff0c;所以应该不算是盗版资源&#xff0c;侵权删 拼UI 提示面板的逻辑 using System.Collections; using System.Col…

大数据——Hive原理

摘要 Apache Hive 是一个基于 Hadoop 分布式文件系统 (HDFS) 的数据仓库软件项目&#xff0c;专为存储和处理大规模数据集而设计。它提供类似 SQL 的查询语言 HiveQL&#xff0c;使用户能够轻松编写复杂的查询和分析任务&#xff0c;而无需深入了解 Hadoop 的底层实现。 Hive…

Firefox扩展程序和Java程序通信

实现Firefox扩展程序&#xff0c;和Java RMI Client端进行通信。 在Firefox工具栏注册按钮&#xff0c;点击按钮后弹出Popup.html页面&#xff0c;引用Popup.js脚本&#xff0c;通过脚本向Java RMI client发送消息&#xff0c;Java RMI Client接收消息后转发到Java RMI Server…

MyBatis的入门操作--打印日志和增删改查(单表静态)

下面介绍注解和xml实现crud的操作 目录 一、日志打印和参数传递 1.1.使用mybatis打印日志 1.2.参数传递细节 二、crud&#xff08;注解实现&#xff09; 2.1.增(insert) 2.2.删(delete) 和 (update) 2.3.查(select) 三、crud&#xff08;xml实现&#xff09; 3.1.准备…

中国居民膳食指南书籍知识点汇总

人如果吃不好&#xff0c;就不能好好思考&#xff0c;好好爱&#xff0c;好好休息。——维吉尼亚伍儿夫 文章目录 书籍简介饮食准则推荐膳食图示 准则一&#xff1a;食物多样&#xff0c;合理搭配合理搭配的方法平衡膳食的科学原理均衡饮食的作用食物功效&#xff08;有科学实验…

02、爬虫数据解析-Re解析

数据解析的目的是不拿到页面的全部内容&#xff0c;只拿到部分我们想要的内容内容。 Re解析就是正则解析&#xff0c;效率高准确性高。学习本节内容前需要学会基础的正则表达式。 一、正则匹配规则 1、常用元字符 . 匹配除换行符以外的字符 \w 匹配字母或数字或下划…