March.11.2022——中缀表达式转化为后缀表达式统一思路

2024-04-28 05:08

本文主要是介绍March.11.2022——中缀表达式转化为后缀表达式统一思路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

March.11.2022

中缀表达式转化为后缀表达式统一思路 (8步)
  1. 初始化两个栈:运算符栈s1和储存中间结果的栈s2;

  2. 从左至右扫描中缀表达式;

  3. 遇到操作数时,将其压s2;

  4. 遇到运算符时,比较其与s1栈顶运算符的优先级:

    1). 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;

    2). 否则,若优先级比栈顶运算符的高,也将运算符压入s1;

    3). 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较;

  5. 遇到括号时:

    1. . 如果是左括号“(”,则直接压入s1
    2. . 如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
  6. 重复步骤2至5,直到表达式的最右边

  7. 将s1中剩余的运算符依次弹出并压入s2

  8. 依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

package Zhan;import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;import java.util.ArrayList;
import java.util.List;
import java.util.Stack;//如果要使用List 包 那必须要导包!! dlt + enterpublic class ZhongZhuiTOHouZhui {public static void main(String[] args) {//完成将中缀表达式 转化为后缀表达式//说明//1.   1+((2+3)*4)-5  转换成   1 2 3 + 4 * + 5 -//2. 因为直接对字符串 进行操作 不方便,所以需要将 “1+((2+3)*4)-5 ”,中缀表达式存到对应的list中// 即“1+((2+3)*4)-5 ” => Arraylist[1,+,(,(,2,+3,),),*,4,-,5]//3.将得到的中缀表达式对应的list 转化为后缀表达式//即 得到了[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5] 需要转换为  1 2 3 + 4 * + 5 -//没有小括号//具体的步骤 有8步String Expression = "1+((2+3)*4)-5";List<String> infixExpressionlist = toInfixExpressionlist(Expression);System.out.println(infixExpressionlist);//逆波兰表达式 (3+4)*5-6; 其中该式子的逆波兰表达式可以写为 3 4 + 5 * 6 -;String sufficExpression = "3 4 + 5 * 6 -";//思路//1.先将 该计算表达式的逆波兰表达式字符串 放到 Arratlist中//2.将 Arraylist 传给一个方法,遍历 Arraylist 配合栈完成计算List<String> list = getlistString(sufficExpression);System.out.println("list" + list);int res = calculate(list);System.out.println("计算的结果是" + res);}//将中缀表达式转化成对应的Listpublic static List<String> toInfixExpressionlist(String s) {//定义一个List 存放中缀表达式  对应的内容List<String> ls = new ArrayList<String>();int i = 0; //作为扫描的指针String str = "";// 对多位数的拼接char c;//每遍历到一个字符 ,就直接放到cdo {//如果 c 是一个非数字的字符 就直接将遍历得到的c加到字符串中if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {ls.add("" + c);i++;} else {//如果 c 是一个数  不为个位数的话就将字符串拼接起来//这里非常容易出问题!!必须将字符串清空!!!!!!!!!str = "";//数字在ASC码表中的值 即为48-57 之间while (i < s.length() && (c = s.charAt(i)) >= 48 && (c = s.charAt(i)) <= 57) {str += c;i++;}ls.add(str);}} while (i < s.length());//扫描完毕 返回lsreturn ls;}//将中缀表达式转换为后缀表达式public static List<String> parseSufExpresionList(List<String> ls) {//创建一个栈 用于存放运算符Stack<String> stack1 = new Stack<String>();//创建一个栈 用于存放数字//但是考虑到 在中转后缀表达式的时候,数字的栈从来没有使用过出栈操作,并且最后还需要逆序输出//这里直接使用List<String> s2;//Stack<String> stack2 = new Stack<>();List<String> s2 = new ArrayList<String>();//遍历lsfor (String item : ls)//如果遍历得到的是一个数 则入栈到s2if (item.matches("\\d+")) {s2.add(item);//请注意 这里是 .equals 不是 .matchs!!!!!} else if (item.equals("(")) {stack1.push(item);} else if (item.equals(")")) {while (!stack1.peek().equals("(")) {s2.add(stack1.pop());}stack1.pop();///将stack1 弹出栈 消除小括号} else {//当item的运算符的优先级小于等于s1栈顶的运算符,将s1栈顶的运算符弹出并加入s2中,再次转到4.1步骤,与i新的运算符的栈顶比较//问题:缺少一个比较运算符优先级的方法while (stack1.size() != 0 && Operation.getValue(stack1.peek()) >= Operation.getValue(item)) {s2.add(stack1.pop());}//还需要将item入栈stack1.push(item);}//将s1剩余的运算符依次弹出并加入s2while(stack1.size()!=0){s2.add(stack1.pop());}return s2;}private static List<String> getlistString(String sufficExpression) {//将后缀表达式按照空格来拆分,拆分成字符串数组String[] split = sufficExpression.split(" ");//创建一个字符串形式的数组列表 用于接收 被拆分的字符串数组ArrayList<String> list = new ArrayList<>();for(String ele:split){list.add(ele);}return list;}//完成对逆波兰表达式的计算// 1.从左往右扫描, 将 3 和 4 压入栈中;//2.遇到 + 号运算符 弹出 4 和 3 (其中 4为栈顶元素,3为次栈顶元素),计算出 3+4 的值,得到7 将结果7入栈//3.将5 入栈//4.遇到 * 运算符 ,弹出5 和 7  计算出 5*7=35 将35入栈//5.遇到6 将6入栈//6.遇到 - 运算符,计算出来 35-6的值 得到最终结果//扫描的过程其实就是对list 的遍历public static int  calculate(List<String> ls){//创建一个栈Stack<String> stack = new Stack<>();//遍历 lsfor(String item:ls){if(item.matches("\\d+")){// 正则表达式如果遍历到的是一个或者多位数 则 入栈stack.push(item);}else { //遍历到的是一个运算符 则pop出两个数字 第一个出栈的是num2 第二个出栈的数命名为num1int num2 = Integer.parseInt(stack.pop());int num1 = Integer.parseInt(stack.pop());//由于出栈的元素的类型为 string  需要转化为int  类型所以调用Integer.parseInt方法 将字符串类型转化为 int 类型方便计算int res = 0;if(item.equals("+")){res = num1+num2;}else if(item.equals("-")){//在此处请注意 出栈的顺序res = num1 - num2;}else if(item.equals("*")){res = num1*num2;}else if(item.equals("/")){res = num1 / num2;}else {throw new RuntimeException("你输入的格式有误,请重新输入");}//请注意 这里使用了一个小技巧:即通过在前后加空格的方法,将整数类型转化为字符串类型stack.push(""+res);}}return Integer.parseInt(stack.pop());}}//编写一个运算符优先级的类 对应不同运算符的优先级class Operation{private static int ADD = 1;private static int SUB = 1;private static int MUL = 2;private static int DIV = 2;//写一个方法,返回优先级对应的数字public static int getValue(String operation){int result = 0;switch (operation){case "+":result = ADD;break;case "-":result = SUB;break;case "*":result = MUL;break;case "/":result = DIV;break;default:System.out.println("不存在该运算符");break;}return result;}}

这篇关于March.11.2022——中缀表达式转化为后缀表达式统一思路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/942390

相关文章

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

usaco 1.2 Palindromic Squares(进制转化)

考察进制转化 注意一些细节就可以了 直接上代码: /*ID: who jayLANG: C++TASK: palsquare*/#include<stdio.h>int x[20],xlen,y[20],ylen,B;void change(int n){int m;m=n;xlen=0;while(m){x[++xlen]=m%B;m/=B;}m=n*n;ylen=0;whi

usaco 1.2 Name That Number(数字字母转化)

巧妙的利用code[b[0]-'A'] 将字符ABC...Z转换为数字 需要注意的是重新开一个数组 c [ ] 存储字符串 应人为的在末尾附上 ‘ \ 0 ’ 详见代码: /*ID: who jayLANG: C++TASK: namenum*/#include<stdio.h>#include<string.h>int main(){FILE *fin = fopen (

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

三相直流无刷电机(BLDC)控制算法实现:BLDC有感启动算法思路分析

一枚从事路径规划算法、运动控制算法、BLDC/FOC电机控制算法、工控、物联网工程师,爱吃土豆。如有需要技术交流或者需要方案帮助、需求:以下为联系方式—V 方案1:通过霍尔传感器IO中断触发换相 1.1 整体执行思路 霍尔传感器U、V、W三相通过IO+EXIT中断的方式进行霍尔传感器数据的读取。将IO口配置为上升沿+下降沿中断触发的方式。当霍尔传感器信号发生发生信号的变化就会触发中断在中断

Jenkins 插件 地址证书报错问题解决思路

问题提示摘要: SunCertPathBuilderException: unable to find valid certification path to requested target...... 网上很多的解决方式是更新站点的地址,我这里修改了一个日本的地址(清华镜像也好),其实发现是解决不了上述的报错问题的,其实,最终拉去插件的时候,会提示证书的问题,几经周折找到了其中一遍博文

如何掌握面向对象编程的四大特性、Lambda 表达式及 I/O 流:全面指南

这里写目录标题 OOP语言的四大特性lambda输入/输出流(I/O流) OOP语言的四大特性 面向对象编程(OOP)是一种编程范式,它通过使用“对象”来组织代码。OOP 的四大特性是封装、继承、多态和抽象。这些特性帮助程序员更好地管理复杂的代码,使程序更易于理解和维护。 类-》实体的抽象类型 实体(属性,行为) -》 ADT(abstract data type) 属性-》成

Java基础回顾系列-第三天-Lambda表达式

Java基础回顾系列-第三天-Lambda表达式 Lambda表达式方法引用引用静态方法引用实例化对象的方法引用特定类型的方法引用构造方法 内建函数式接口Function基础接口DoubleToIntFunction 类型转换接口Consumer消费型函数式接口Supplier供给型函数式接口Predicate断言型函数式接口 Stream API 该篇博文需重点了解:内建函数式