栈的应用-逆波兰式
Posted sang-bit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈的应用-逆波兰式相关的知识,希望对你有一定的参考价值。
---恢复内容开始---
普通的计算方式,也叫中缀表达式计算机识别及正确运用需要耗费大量的资源
23+45*2-(8+2)
计算机想要正确计算出此时的结果需要十分复杂,更何况情况十分多变。
逆波兰式:又叫做后缀表达式,它能去除中缀表达式的括号。十分符合计算机的计算思维,能极大提高效率
表达式不能用字符串进行存储,因为这将无法分辨,应用集合(ArrayList,LinkedList存储)
23 45 2 * 8 2 + - +
那么中缀表达式是如何变成后缀表达式的呢?原则如下:
1.首先把普通的表达式按照运算符分离出来放在一个集合E中,比如1+2*3 分离后集合里的元素就是 1 + 2 * 3 五个元素
2.再定义一个集合R(最好是字符串类型的集合,免得后面要转类型),主要是用来存放逆波兰表达式的,还有定义一个堆栈(存储运算符用),最后从左到右遍历集合E
3.遍历E的规则如下:
3.1如果该元素是数字,直接把它添加到集合R中
3.2否则它肯定是运算符,那么再进行判断
3.2.1如果该元素是左括号,或者当时栈为空,那么直接入栈
3.2.2如果该元素是右括号,则把栈内的运算符出栈并添加到集合R中,直到遇到第一个左括号结束(左括号也出栈但不添加到R)
3.2.3否则该元素是普通的运算符(也就是+-*/之类的),那么用该运算符和栈内的运算符号比较优先级,如果该运算符的优先级比栈内的运算符
优先级高 或者 栈为空,则直接入栈,否则把栈内的运算符出栈并添加到R中,再判断下个栈内的运算符优先级,直到遇栈内的运
算符优先级<=该运算符或者栈为空时再把该运算符入栈
3.3整个过程完成后,再把栈内的所有运算符出栈并添加到R中
成功得到后缀表达式,但计算机又是如何通过后缀表达式计算出结果的呢?
这就需要运用到数据结构栈的特点
- 把上面的数值依次压入栈,若遇到运算符,则依次拿出栈顶的两个元素用该运算符进行运算,把结果在压入栈
- 直到后缀表达式全部读完,栈顶的数就是运算结果
上式具体流程就是;
- 依次把23 45 2 压入栈
- 计算45*2=90,90压入栈
- 依次把8 2 压入栈
- 计算8+2=10 10压栈
- 计算90-10=80 80压入栈
- 计算23+80=103 103压入栈
- 提取栈顶103
代码如下;
import java.util.ArrayList; import java.util.ListIterator; import java.util.Scanner; import java.util.Stack; public class test { /** * 将字符串转换为中序表达式 */ public static ArrayList<String> toZhong(String s){ ArrayList<String> arrayList=new ArrayList();//存贮中缀表达式 for(int i=0;i<s.length();i++){ String str=""; if(s.charAt(i)<48||s.charAt(i)>57){//48:0,57:9 str=str+s.charAt(i); arrayList.add(str); } else{ while(i<s.length()&&s.charAt(i)>=48&&s.charAt(i)<=57){ str=str+s.charAt(i); i++; } arrayList.add(str); i--; } } return arrayList; } --------------------------------------------------------------------------------------- /* * 把中缀表达式转成逆波兰式 */ public static ArrayList<String> toNishi(ArrayList<String> list){ ArrayList<String> arr=new ArrayList();//用表存储逆波兰式 Stack<String> timeStack=new Stack();//临时存储操作符 for(String s:list){ if(s.matches("\\d+")){ arr.add(s); } else if(s.equals("(")){ timeStack.push(s); } else if(s.equals(")")){ while(!(timeStack.peek().equals("("))){ arr.add(timeStack.pop()); } } else{ while(timeStack.size()!=0&&getValue(s)<getValue(timeStack.peek())){ arr.add(timeStack.pop()); } timeStack.push(s); } } while(timeStack.size()!=0){ arr.add(timeStack.pop()); } return arr; } public static int getValue(String ss) { if (ss.equals("+")) { return 1; } else if (ss.equals("-")) { return 1; } else if (ss.equals("*")) { return 2; } else if (ss.equals("\\")) { return 2; } return 0; } ------------------------------------------------------------------------------------------ //计算逆波兰式结果 public static int jisuan(ArrayList<String> arr){ Stack<Integer> jieguo=new Stack<Integer>(); for(String s:arr){ if(s.matches("\\d+")){ jieguo.push(Integer.parseInt(s)); } else if(jieguo.size()>=2){ Integer a=jieguo.pop(); Integer b=jieguo.pop(); if(s.equals("+")){ jieguo.push(b+a); } else if(s.equals("-")){ jieguo.push(b-a); } else if(s.equals("*")){ jieguo.push(b*a); } else if(s.equals("//")){ jieguo.push(b/a); } } } return jieguo.pop(); }
---恢复内容结束---
以上是关于栈的应用-逆波兰式的主要内容,如果未能解决你的问题,请参考以下文章