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


目录
相关文章
|
4天前
|
自然语言处理 Java API
Java 8的Stream API和Optional类:概念与实战应用
【5月更文挑战第17天】Java 8引入了许多重要的新特性,其中Stream API和Optional类是最引人注目的两个。这些特性不仅简化了集合操作,还提供了更好的方式来处理可能为空的情况,从而提高了代码的健壮性和可读性。
26 7
|
6天前
|
前端开发 Java 测试技术
Java一分钟之Spring MVC:构建Web应用
【5月更文挑战第15天】Spring MVC是Spring框架的Web应用模块,基于MVC模式实现业务、数据和UI解耦。常见问题包括:配置DispatcherServlet、Controller映射错误、视图解析未设置、Model数据传递遗漏、异常处理未配置、依赖注入缺失和忽视单元测试。解决这些问题可提升代码质量和应用性能。注意配置`web.xml`、`@RequestMapping`、`ViewResolver`、`Model`、`@ExceptionHandler`、`@Autowired`,并编写测试用例。
293 3
|
6天前
|
Java 测试技术
Java一分钟之-正则表达式在Java中的应用
【5月更文挑战第14天】正则表达式是Java中用于文本处理的强大力量,通过`java.util.regex`包支持。常见问题包括元字符的理解、边界匹配和贪婪/懒惰量词的使用。错误通常涉及未转义特殊字符、不完整模式或过度匹配。要避免这些问题,需学习实践、使用在线工具和测试调试。示例代码展示了如何验证邮箱地址。掌握正则表达式需要不断练习和调试。
26 2
|
1天前
|
Java 程序员 API
Java 8 Lambda 表达式和Stream API:概念、优势和实战应用
【5月更文挑战第20天】在Java 8中,Lambda 表达式和Stream API是两个非常强大的特性,它们显著改变了Java程序员处理数据和编写代码的方式。本篇技术文章将深入探讨这些特性的概念、优点,并提供实战示例,帮助理解如何有效地利用这些工具来编写更简洁、更高效的代码。
19 6
|
3天前
|
Java
深入理解Java并发编程:线程池的应用与优化
【5月更文挑战第18天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将了解线程池的基本概念,应用场景,以及如何优化线程池的性能。通过实例分析,我们将看到线程池如何提高系统性能,减少资源消耗,并提高系统的响应速度。
13 5
|
3天前
|
算法 搜索推荐 Java
滚雪球学Java(33):数组算法大揭秘:应用案例实战分享
【5月更文挑战第8天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
31 8
滚雪球学Java(33):数组算法大揭秘:应用案例实战分享
|
5天前
|
安全 Java Android开发
构建高效Android应用:探究Kotlin与Java的性能差异
【5月更文挑战第16天】 在移动开发领域,性能一直是开发者关注的焦点。随着Kotlin语言的普及,其与Java在Android应用中的性能表现成为热门话题。本文将深入分析Kotlin和Java在Android平台上的性能差异,并通过实际测试数据来揭示二者在编译速度、应用启动时间以及运行效率方面的表现。我们的目标是为开发者提供一个参考依据,以便在选择合适的编程语言时做出更加明智的决策。
|
6天前
|
Java 开发工具 Maven
java解析apk获取应用信息
请注意,你需要替换"path/to/your/apkfile.apk"为你的APK文件的实际路径。
12 0
|
6天前
|
Java 编译器 开发者
Java一分钟之-Java注解的理解与应用
【5月更文挑战第12天】本文介绍了Java注解的基础知识和常见应用,包括定义、应用和解析注解。注解在编译检查、框架集成和代码生成等方面发挥重要作用。文章讨论了两个易错点:混淆保留策略和注解参数类型限制,并提供了避免策略。提醒开发者避免过度使用注解,以保持代码清晰。理解并恰当使用注解能提升代码质量。
14 3
|
6天前
|
Java API 开发者
Java中Lambda表达式的深入理解与应用
【5月更文挑战第12天】在Java 8之后,Lambda表达式已经成为了Java开发者必备的技能之一。Lambda表达式以其简洁、灵活的特点,大大提高了编程的效率。本文将深入探讨Lambda表达式的基本概念,语法规则,以及在实际开发中的应用,帮助读者更好地理解和使用Lambda表达式。