栈的简单应用(利用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


目录
相关文章
|
2月前
|
人工智能 安全 Java
Java和Python在企业中的应用情况
Java和Python在企业中的应用情况
62 7
|
12天前
|
安全 算法 Java
Java CAS原理和应用场景大揭秘:你掌握了吗?
CAS(Compare and Swap)是一种乐观锁机制,通过硬件指令实现原子操作,确保多线程环境下对共享变量的安全访问。它避免了传统互斥锁的性能开销和线程阻塞问题。CAS操作包含三个步骤:获取期望值、比较当前值与期望值是否相等、若相等则更新为新值。CAS广泛应用于高并发场景,如数据库事务、分布式锁、无锁数据结构等,但需注意ABA问题。Java中常用`java.util.concurrent.atomic`包下的类支持CAS操作。
43 2
|
1月前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
55 5
|
2月前
|
缓存 Java 开发者
Java多线程并发编程:同步机制与实践应用
本文深入探讨Java多线程中的同步机制,分析了多线程并发带来的数据不一致等问题,详细介绍了`synchronized`关键字、`ReentrantLock`显式锁及`ReentrantReadWriteLock`读写锁的应用,结合代码示例展示了如何有效解决竞态条件,提升程序性能与稳定性。
159 6
|
1月前
|
监控 Java 数据库连接
Java线程管理:守护线程与用户线程的区分与应用
在Java多线程编程中,线程可以分为守护线程(Daemon Thread)和用户线程(User Thread)。这两种线程在行为和用途上有着明显的区别,了解它们的差异对于编写高效、稳定的并发程序至关重要。
37 2
|
2月前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
69 6
|
2月前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
55 2
|
2月前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
2月前
|
Java 测试技术 API
Java 反射机制:深入解析与应用实践
《Java反射机制:深入解析与应用实践》全面解析Java反射API,探讨其内部运作原理、应用场景及最佳实践,帮助开发者掌握利用反射增强程序灵活性与可扩展性的技巧。
119 4
|
2月前
|
Java BI API
Java Excel报表生成:JXLS库的高效应用
在Java应用开发中,经常需要将数据导出到Excel文件中,以便于数据的分析和共享。JXLS库是一个强大的工具,它基于Apache POI,提供了一种简单而高效的方式来生成Excel报表。本文将详细介绍JXLS库的使用方法和技巧,帮助你快速掌握Java中的Excel导出功能。
73 6