前缀,后缀表达式(逆波兰表达式),中缀表达式转为对应的后缀表达式,逆波兰计算器的实现(java)

您所在的位置:网站首页 前缀表达式计算 前缀,后缀表达式(逆波兰表达式),中缀表达式转为对应的后缀表达式,逆波兰计算器的实现(java)

前缀,后缀表达式(逆波兰表达式),中缀表达式转为对应的后缀表达式,逆波兰计算器的实现(java)

#前缀,后缀表达式(逆波兰表达式),中缀表达式转为对应的后缀表达式,逆波兰计算器的实现(java)| 来源: 网络整理| 查看: 265

波兰表达式 1.前缀表达式(波兰表达式)2.后缀表达式(逆波兰表达式)3.完成一个简易版的逆波兰计算器4.中缀表达式转为后缀表达式5.完整逆波兰计算器的实现

1.前缀表达式(波兰表达式)

1.前缀表达式的定义

前缀表达式的运算符位于操作符之前 例如:(3+4)*5-6对应的前缀表达式就是 - * + 3 4 5 6

2.前缀表达式的计算机求值 从右至左扫描表达式,遇到数字时就将数字压入堆栈,遇到运算符时弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素和次顶元素),并将结果入栈;重复上述过程知道表达式最左端,最后运算得出的值即为表达式的结果

举例: (3+4)*5-6对应的前缀表达式就是 - * + 3 4 5 6,针对前缀表达式求值步骤如下:

从左至右扫描,将6,5,4,3压入堆栈遇到+运算符,弹出3和4(3为栈顶元素,4为次顶元素),计算出3+4的值,得7,再将7入栈接下来是*运算符,弹出7和5,得35,将35入栈最后是-运算符,计算35-6,得29,由此得出最终结果

中缀表达式就是我们常见的表达式, 比如:(3+4)*5-6

2.后缀表达式(逆波兰表达式)

后缀表达式定义:运算符位于操作符之后 举例: (3+4)*5-6对应的后缀表达式就是 3 4 + 5 * 6 - 在这里插入图片描述 后缀表达式的计算机求值 从左至右扫描表达式,遇到数字将数字压入栈中,遇到运算符时弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素和栈顶元素),并将结果入栈;重复上述过程知道表达式最右端,最后运算得出的值即为表达式的结果

例如: (3+4)*5-6对应的前缀表达式就是 - * + 3 4 5 6,针对前缀表达式求值步骤如下:

从左到右扫描,将3和4压入栈中遇到+运算符,弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈将5入栈接下来是运算符,由此弹出5和7,计算75=35,将35入栈将6入栈最后是 - 运算符,计算出35-6的值29,得出最终结果 3.完成一个简易版的逆波兰计算器

要求: 输入一个逆波兰表达式(后缀表达式),使用栈(stack),计算其结果

思路分析如上 后缀表达式的计算机求值

代码实现:

//完成对逆波兰表达式的运算 /* * 1)从左至右扫描,将3和4压入堆栈; 2)遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈; 3)将5入栈; 4)接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈; 5)将6入栈; 6)最后是-运算符,计算出35-6的值,即29,由此得出最终结果 */ public static int calculate(List ls) { // 创建栈, 只需要一个栈即可 Stack stack = new Stack(); // 遍历 ls for (String item : ls) { // 这里使用正则表达式来取出数 if (item.matches("\\d+")) { // 匹配的是多位数 // 入栈 stack.push(item); } else { // pop出两个数,并运算, 再入栈 int num2 = Integer.parseInt(stack.pop()); int num1 = Integer.parseInt(stack.pop()); 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("运算符有误"); } //把res 入栈 stack.push("" + res); } } //最后留在stack中的数据是运算结果 return Integer.parseInt(stack.pop()); } } 4.中缀表达式转为后缀表达式

中缀表达式转后缀表达式思路分析

1.初始化两个栈:运算符栈s1和储存中间结果的栈s2 2.从左至右扫描中缀表达式 3.遇到操作数,将其压入s2 4.遇到运算符,比较其与s1栈顶运算符的优先级

如果s1为空,或栈顶运算符为左括号“(”,直接将此运算符入栈否则,若优先级比栈顶运算符的高,也将运算符入s1否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4.1)与s1中新的运算符相比较

5.遇到括号时

如果是左括号“(”,则直接压入s1如果是右括号“)”则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃

6.重复步骤2~5,直到表达式的最右边 7.将s1中剩余的运算符依次弹出并压入s2 8.依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

举例说明: 将中缀表达式“1+((2+3)*4)-5”转为后缀表达式的过程如下

举例 其结果为123+4*+5-

5.完整逆波兰计算器的实现

代码实现:

import java.util.ArrayList; import java.util.List; import java.util.Stack; public class PolandNotation { public static void main(String[] args) { //完成将一个中缀表达式转成后缀表达式的功能 //说明 //1. 1+((2+3)×4)-5 => 转成 1 2 3 + 4 × + 5 – //2. 因为直接对str 进行操作,不方便,因此 先将 "1+((2+3)×4)-5" =》 中缀的表达式对应的List // 即 "1+((2+3)×4)-5" => ArrayList [1,+,(,(,2,+,3,),*,4,),-,5] //3. 将得到的中缀表达式对应的List => 后缀表达式对应的List // 即 ArrayList [1,+,(,(,2,+,3,),*,4,),-,5] =》 ArrayList [1,2,3,+,4,*,+,5,–] String expression = "1+((2+3)*4)-5";//注意表达式 List infixExpressionList = toInfixExpressionList(expression); System.out.println("中缀表达式对应的List=" + infixExpressionList); // ArrayList [1,+,(,(,2,+,3,),*,4,),-,5] List suffixExpreesionList = parseSuffixExpreesionList(infixExpressionList); System.out.println("后缀表达式对应的List" + suffixExpreesionList); //ArrayList [1,2,3,+,4,*,+,5,–] System.out.printf("expression=%d", calculate(suffixExpreesionList)); } //即 ArrayList [1,+,(,(,2,+,3,),*,4,),-,5] =》 ArrayList [1,2,3,+,4,*,+,5,–] //方法:将得到的中缀表达式对应的List => 后缀表达式对应的List public static List parseSuffixExpreesionList(List ls) { //定义两个栈 Stack s1 = new Stack(); // 符号栈 //说明:因为s2 这个栈,在整个转换过程中,没有pop操作,而且后面我们还需要逆序输出 //因此比较麻烦,这里我们就不用 Stack 直接使用 List s2 //Stack s2 = new Stack(); // 储存中间结果的栈s2 List s2 = new ArrayList(); // 储存中间结果的Lists2 //遍历ls for(String item: ls) { //如果是一个数,加入s2 if(item.matches("\\d+")) { s2.add(item); } else if (item.equals("(")) { s1.push(item); } else if (item.equals(")")) { //如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2, //直到遇到左括号为止,此时将这一对括号丢弃 while(!s1.peek().equals("(")) { s2.add(s1.pop()); } s1.pop();//!!! 将 ( 弹出 s1栈, 消除小括号 } else { //当item的优先级小于等于s1栈顶运算符, //将s1栈顶的运算符弹出并加入到s2中, //再次转到(4.1)与s1中新的栈顶运算符相比较 //问题:我们缺少一个比较优先级高低的方法 while(s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item) ) { s2.add(s1.pop()); } //还需要将item压入栈 s1.push(item); } } //将s1中剩余的运算符依次弹出并加入s2 while(s1.size() != 0) { s2.add(s1.pop()); } //注意因为是存放到List, //因此按顺序输出就是对应的后缀表达式对应的List return s2; } //方法:将 中缀表达式转成对应的List // s="1+((2+3)×4)-5"; public static List toInfixExpressionList(String s) { //定义一个List,存放中缀表达式 对应的内容 List ls = new ArrayList(); int i = 0; //这是一个指针,用于遍历 中缀表达式字符串 String str; // 对多位数的拼接 char c; // 每遍历到一个字符,就放入到c do { //如果c是一个非数字,我需要加入到ls if((c=s.charAt(i)) 57) {//ASCII码 ls.add("" + c); i++; //i需要后移 } else { //如果是一个数,需要考虑多位数 str = ""; //先将str 置成"" '0'[48]->'9'[57] while(i = 48 && (c=s.charAt(i)) //将 suffixExpression 分割,以空格来分割 String[] split = suffixExpression.split(" "); List 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,计算出7×5=35,将35入栈; 5)将6入栈; 6)最后是-运算符,计算出35-6的值,即29,由此得出最终结果 */ public static int calculate(List ls) { // 创建栈, 只需要一个栈即可 Stack stack = new Stack(); // 遍历 ls for (String item : ls) { // 这里使用正则表达式来取出数 if (item.matches("\\d+")) { // 匹配的是多位数 // 入栈 stack.push(item); } else { // pop出两个数,并运算, 再入栈 int num2 = Integer.parseInt(stack.pop()); int num1 = Integer.parseInt(stack.pop()); 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("运算符有误"); } //把res 入栈 stack.push("" + res); } } //最后留在stack中的数据是运算结果 return Integer.parseInt(stack.pop()); } } //编写一个类 Operation 可以返回一个运算符 对应的优先级 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("不存在该运算符" + operation); break; } return result; } }

本篇博客参考内容



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3