栈的简单应用——四则运算(一)
2013-01-08 09:36
441 查看
在Java中用堆栈实现四则运算是一种很巧妙的方法。栈的先进后出原理可以很方便地判断并控制加、减、乘、除的优先级,利用这一优势,我们可以很高效的将一个中缀表达式转换为去除符号优先级的后缀表达式。
数学上的四则运算算术式,比如:2+3*4
后缀表达式
不考虑符号优先级的表达式,比如:(2+3*4)经过转换之后的结果是(234*+),可以理解为将我们解决数学上四则运算表达式的逻辑过程转换为程序方便操作的表达式。
如何将中缀表达式转换为后缀表达式
首先,将中缀表达式转换为数组形式,然后线性遍历数组,遇到的字符有两种(暂时只处理两种)。
数字不做任何处理,直接追加到要输出的字符串中;
符号则进行如下操作:
1、栈操作,如果栈是空栈,直接将操作符号入栈;
2、如果栈为非空,查看栈顶符号的优先级是否比当前符号的优先级高,高则将栈顶符号压出并追加到要输出的字符串中,否则直接将当前符号压入栈中;
3、如果当前符号未入栈,重复步骤2,直到当前符号入栈为止;
4、继续执行遍历操作。
最后,遍历结束,将栈中的符号全部压出,按顺序追加到输出字符串中。
如何计算后缀表达式
很简单,依次遍历后缀表达式中的每一个字符,是数字则入栈,是符号则压出栈顶的两个元素,按照相应的符号进行计算,并将计算结果入栈。
标准表达式输入
校验输入的表达式是否合法
将中缀表达式转为后缀表达式
计算后缀表达式
执行程序
执行结果
一、基础知识
中缀表达式数学上的四则运算算术式,比如:2+3*4
后缀表达式
不考虑符号优先级的表达式,比如:(2+3*4)经过转换之后的结果是(234*+),可以理解为将我们解决数学上四则运算表达式的逻辑过程转换为程序方便操作的表达式。
如何将中缀表达式转换为后缀表达式
首先,将中缀表达式转换为数组形式,然后线性遍历数组,遇到的字符有两种(暂时只处理两种)。
数字不做任何处理,直接追加到要输出的字符串中;
符号则进行如下操作:
1、栈操作,如果栈是空栈,直接将操作符号入栈;
2、如果栈为非空,查看栈顶符号的优先级是否比当前符号的优先级高,高则将栈顶符号压出并追加到要输出的字符串中,否则直接将当前符号压入栈中;
3、如果当前符号未入栈,重复步骤2,直到当前符号入栈为止;
4、继续执行遍历操作。
最后,遍历结束,将栈中的符号全部压出,按顺序追加到输出字符串中。
如何计算后缀表达式
很简单,依次遍历后缀表达式中的每一个字符,是数字则入栈,是符号则压出栈顶的两个元素,按照相应的符号进行计算,并将计算结果入栈。
二、需求分析
实现十以内自然数的加减乘除。直接使用栈,可以在线性时间内完成(O(n))。三、代码实现
符号优先级的初始化private static Map<String,Integer> priorityMap = new HashMap<String,Integer>(); private static String symPattern = ""; private Stack<String> stack = new Stack<String>(); static{ symPattern = "[+\\-*/]"; priorityMap.put("+", -1); priorityMap.put("-", -1); priorityMap.put("*", 1); priorityMap.put("/", 1); }
标准表达式输入
public String input(){ Scanner scanner = new Scanner(System.in); String str = ""; if(scanner.hasNext()){ str += scanner.next(); } System.out.println("the value of infix is " + str); return str; }
校验输入的表达式是否合法
public boolean checkInput(String input) throws Exception{ char[] array = input.toCharArray(); for(int i=0;i<array.length;i++){ if(i<array.length - 1){ String prev = String.valueOf(array[i]); String next = String.valueOf(array[++i]); //减号需要转义! if(!prev.matches("[\\d+\\-*/]")){ throw new Exception("输入中含有非法字符,请重新输入!"); }else if(prev.matches("\\d")&&next.matches("\\d")){ throw new Exception("输入的数字不在[0-9]之间!"); }else if(prev.matches("[+\\-*/]")&&next.matches("[+\\-*/]")){ throw new Exception("输入了连续的符号!请重新输入!"); }else if(prev.matches("/")&&next.matches("0")){ throw new Exception("分母不能为零!"); } } } return true; }
将中缀表达式转为后缀表达式
public String generateSuffixExp(String input){ char[] array = input.toCharArray(); String suffix = ""; for(int i = 0;i < array.length;i++){ String atom = String.valueOf(array[i]); if(atom.matches(symPattern)){ if(stack.isEmpty()){ stack.push(atom); }else{ while(!stack.isEmpty()&&priorityMap.get(stack.peek()) >= priorityMap.get(atom)){ suffix += stack.pop(); } stack.push(atom); } }else{ suffix +=atom; } } while(!stack.isEmpty()){ suffix += stack.pop(); } return suffix; }
计算后缀表达式
public int resuleCompute(String suffix){ int result = 0; for(int i=0;i<suffix.length();i++){ String atom = String.valueOf(suffix.charAt(i)); if(atom.matches("\\d")){ stack.push(atom); }else{ int a = Integer.parseInt(stack.pop()); int b = Integer.parseInt(stack.pop()); result = this.getMiddleResult(a, b, atom); stack.push(""+result); } } stack.clear(); return result; } public int getMiddleResult(int a,int b,String symbol){ if("+".equals(symbol)){ return b + a; }else if("-".equals(symbol)){ return b - a; }else if("*".equals(symbol)){ return b * a; }else{ return b / a; } }
执行程序
public static void main(String[] args) throws Exception{ Cal_Version_1 cal = new Cal_Version_1(); while(true){ String input = cal.input(); if(cal.checkInput(input)){ String suffix = cal.generateSuffixExp(input); System.out.println("the value of suffix is " + suffix); System.out.println("the result of exp is " + cal.resuleCompute(suffix)); } } }
执行结果
1+2*3*4+4/2 the value of infix is 1+2*3*4+4/2 the value of suffix is 123*4*+42/+ the result of exp is 27
三、结果讨论
程序可以正确地执行了,但是它所处理的问题还有很大的局限性,如果我们要进行十位或百位或者更大数字的四则运算,程序能否正常运行?这种情况又该如何实现呢?如果输入小数呢?相关文章推荐
- 栈的应用--简单四则运算
- 运算符重载简单应用之分数四则运算
- winform程序之comboBox控件应用四则运算(简单)
- 栈的简单应用——四则运算(三)
- 栈的应用:简单加减乘除四则运算——2018/01/06思考
- java SE 数组及简单应用
- Aop简单应用实例,注解模式
- 简单应用场景下使用缓存&redis等
- 简单分析:IPS与IDS的价值与应用比较
- Python 中的 lambda 表达式及其简单应用
- 动态联编和虚函数的简单应用
- Drools 简单应用实例2
- Ansible 配置 & 简单应用
- COM组件设计与应用(四)---简单调用组件
- 栈的应用--四则运算 c++
- WCF RIA Services 简单应用
- Android XmlPullParser的简单应用
- SBC音频编解码算法在无线音频传输上的简单应用
- interface / abstract 简单应用
- 关于管道命令的一些简单应用