栈的简单应用(利用Stack进行四则混合运算)(JAVA)

简介: 中缀表达式转后缀表达式图解,代码实现过程,完整代码,利用后缀表达式求值,完整代码

首先我们得先了解逆波兰表达式

中缀表达式转后缀表达式

所谓的中缀表达式其实就是我们平时写的例如:;而它的后缀表达式(也成为逆波兰表达式)

后缀表达式:指的是不包含括号运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行不再考虑运算符的优先规则)。

我们如果要利用程序来进行四则混合运算最重要的就是将输入的中缀表达式转后缀表达式

首先我们假设运算符中只有 加 减 乘 除 和 括号不然的话程序太复杂了。

图解

c2awgdfvou5n4_a4b2749a43604c78abbf12a146c03c79.png

代码实现过程:

首先我们先写一个方法 返回值是动态字符串数组(为了后面好计算),形参为字符串类型(因为输入值不只有数字还有运算符)。这里会用到栈所以也定义一个栈。

publicArrayList<String>midChangeEng(Stringstr) {
//这里用动态数组就不用担心不够用ArrayList<String>ret=newArrayList<String>();
Stack<Character>stack=newStack<>();
    }

image.gif

此时再创建一个新方法用来判断传入字符是不是运算符

publicbooleanisOperator(chars) {
if (s=='+'||s=='-'||s=='*'||s=='/'||s=='('||s==')') {
returntrue;
        }
returnfalse;
    }

image.gif

我们再利用运算符再ASCII码中的位置,创建一个数组用来表示它们的优先级

image.png

int[] able= {1,0,0,0,0,1};//分别代表 * + (null) - (null) / 的优先级

image.gif

利用循环遍历字符串

//遍历字符串for (inti=0; i<str.length(); i++) {
chara=str.charAt(i);
Stringtmp="";//用来暂时存储出栈的数字if (isOperator(a)) {
//是操作数            }else{
//如果是数字就放到ret中            }
        }
returnret;

image.gif

对操作数的操作 ,可是此段代码中重复代码过多,所以可以将其封装成一个方法。

if (isOperator(a)) {
//是操作数switch (a) {
case'+'://判断如果优先级不大于栈顶的元素那么就先出栈在入栈if(!stack.isEmpty()) {//出栈while(!stack.isEmpty() &&stack.peek() !='('&&able[(int)stack.peek() -42] >=able[(int)a-42]) {
Stringb="";
b+=stack.pop();
ret.add(b);
                            }
                        }
stack.push(a);
break;
case'-':
if(!stack.isEmpty()) {//出栈while(!stack.isEmpty() &&stack.peek() !='('&&able[(int)stack.peek() -42] >=able[(int)a-42]) {
Stringb="";
b+=stack.pop();
ret.add(b);
                            }
                        }
stack.push(a);
break;
case'*':
if(!stack.isEmpty()) {//出栈while(!stack.isEmpty() &&stack.peek() !='('&&able[(int)stack.peek() -42] >=able[(int)a-42]) {
Stringb="";
b+=stack.pop();
ret.add(b);
                            }
                        }
stack.push(a);
break;
case'/':
if(!stack.isEmpty()) {//出栈while(!stack.isEmpty() &&stack.peek() !='('&&able[(int)stack.peek() -42] >=able[(int)a-42]) {
Stringb="";
b+=stack.pop();
ret.add(b);
                            }
                        }
stack.push(a);
break;
case'(':
stack.push(a);
break;
case')':
while(!stack.isEmpty() &&stack.peek() !='(') {
Stringb="";
b+=stack.pop();
ret.add(b);
                        }
stack.pop();//删除‘(’break;
                }
            }

image.gif

如果是数字就进行以下操作

else{
//如果是数字就放到ret中Stringtmp="";
while(i<str.length() &&!isOperator(str.charAt(i))) {//数字有可能是多位的tmp+=str.charAt(i);
i++;
                }
i--;
ret.add(tmp);
            }

image.gif

再出函数之前要先将栈里面的全部导出来

//将栈里面剩余的全部出栈while(!stack.isEmpty()) {
Stringb="";
b+=stack.pop();
ret.add(b);
        }
returnret;

image.gif

完整代码:

publicstaticArrayList<String>midChangeEng(Stringstr) {
//这里用动态数组就不用担心不够用ArrayList<String>ret=newArrayList<String>();
Stack<Character>stack=newStack<>();
int[] able= {1,0,0,0,0,1};//分别代表 * + (null) - (null) / 的优先级//遍历字符串for (inti=0; i<str.length(); i++) {
chara=str.charAt(i);
if (isOperator(a)) {
//是操作数switch (a) {
case'+'://判断如果优先级不大于栈顶的元素那么就先出栈在入栈abcd(ret, stack, able, a);
break;
case'-':
abcd(ret, stack, able, a);
break;
case'*':
abcd(ret, stack, able, a);
break;
case'/':
abcd(ret, stack, able, a);
break;
case'(':
stack.push(a);
break;
case')':
while(!stack.isEmpty() &&stack.peek() !='(') {
Stringb="";
b+=stack.pop();
ret.add(b);
                        }
stack.pop();//删除‘(’break;
                }
            }else{
//如果是数字就放到ret中Stringtmp="";
while(i<str.length() &&!isOperator(str.charAt(i))) {//数字有可能是多位的tmp+=str.charAt(i);
i++;
                }
i--;
ret.add(tmp);
            }
        }
//将栈里面剩余的全部出栈while(!stack.isEmpty()) {
Stringb="";
b+=stack.pop();
ret.add(b);
        }
returnret;
    }

image.gif

image.png

利用后缀表达式求值:


这部分比较简单所以就直接展示了

image.png

完整代码:

publicintevalRPN(String[] tokens) {
Stack<Integer>stack=newStack<>();
for (inti=0; i<tokens.length; i++) {
if (isOperator(tokens[i])) {
intnum2=stack.pop();
intnum1=stack.pop();
switch(tokens[i].charAt(0)) {
case'+':
stack.push(num1+num2);
break;
case'-':
stack.push(num1-num2);
break;
case'*':
stack.push(num1*num2);
break;
case'/':
stack.push(num1/num2);
break;
                    }
                }else {
stack.push(Integer.parseInt(tokens[i]));
                }
            }
returnstack.pop();
        }
publicbooleanisOperator(Stringstr) {
if (str.length() !=1) {
returnfalse;
            }
if (str.charAt(0) =='+'||str.charAt(0) =='-'||str.charAt(0) =='*'||str.charAt(0) =='/') {
returntrue;
            }
returnfalse;
        }

image.gif


目录
相关文章
|
14天前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
|
23天前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
16天前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
29 3
|
26天前
|
SQL 监控 Java
技术前沿:Java连接池技术的最新发展与应用
本文探讨了Java连接池技术的最新发展与应用,包括高性能与低延迟、智能化管理和监控、扩展性与兼容性等方面。同时,结合最佳实践,介绍了如何选择合适的连接池库、合理配置参数、使用监控工具及优化数据库操作,为开发者提供了一份详尽的技术指南。
31 7
|
24天前
|
SQL Java 数据库连接
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,有效减少连接开销,提升访问效率。本文介绍了连接池的工作原理、优势及实现方法,并提供了HikariCP的示例代码。
39 3
|
24天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
44 2
|
25天前
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
13 1
|
28天前
|
存储 算法 Java
🧠Java零基础 - Java栈(Stack)详解
【10月更文挑战第17天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
20 2
|
26天前
|
Java 开发者
Java中的多线程基础与应用
【10月更文挑战第24天】在Java的世界中,多线程是提高效率和实现并发处理的关键。本文将深入浅出地介绍如何在Java中创建和管理多线程,以及如何通过同步机制确保数据的安全性。我们将一起探索线程生命周期的奥秘,并通过实例学习如何优化多线程的性能。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往高效编程的大门。
17 0
下一篇
无影云桌面