使用堆栈将缺少左括号的表达式补全并计算其值
来源:互联网 发布:学吉他软件下载 编辑:程序博客网 时间:2024/05/02 08:30
问题描述:输入一个缺少左括号的表达式,打印出其补全括号的中序表达式,并计算表达式的值。例如给定表达式:
1+2) * 3-4) * 5-6)))
得到输出:
((1+2) * ((3-4) * (5-6)))
计算得到其值为3
问题分析:计算表达式的问题通常使用堆栈。有的算法中利用操作符的优先级以及复杂的记录过程,其实只要利用好堆栈的特性,任何多余的操作都是完全没有必要的。这里首先考虑计算出表达式的值的问题,以此思路推及补全表达式的问题。
由于所计算的表达式是由数字和操作符构成的,因而解析表达式的时候需要使用两个堆栈分别存放数字和操作符。将表达式分别入栈,每当遇到右括号时出栈计算子表达式,将结果再次入栈参与下一次的计算。
public class Test1{ public static boolean isNumber(char s) { return (48<=s&&s<=57)?true:false; } public static boolean isOpr(char s) { return (s=='+'||s=='-'||s=='*'||s=='/')?true:false; } public static void main(String[] args) { In in=new In("D:\\expression.txt"); String string=in.readAll(); char[] word=string.toCharArray(); ListStack<Character> oprStack=new ListStack<>();// 数字 ListStack<Integer> numStack=new ListStack<>();// 操作符 for (int i = 0; i < word.length; i++) { if (isNumber(word[i])) {// 数字 numStack.push(word[i]-48); }else if (isOpr(word[i])) {// 操作符 oprStack.push(word[i]); }else if (word[i]==')') { // 遇到右括号的时候计算子表达式 int right=numStack.pop(); int left=numStack.pop(); char opr=oprStack.pop(); int result=0; switch (opr) { case '+': result=left+right; break; case '-': result=left-right; break; case '*': result=left*right; break; case '/': result=left/right; break; default: break; } // 最后将子表达式的结果入栈参与下次计算 numStack.push(result); } } // 程序最后操作符的堆栈为空,数字的堆栈中就是最后的计算结果 System.out.println(numStack.pop()); }}
可见整个算法是非常简单的。接着要将表达式的左括号补全,应该如何做呢?首先会想到要去找插入左括号的位置,而左括号又取决于右括号的迭代层次,因此要想通过记录位置的方法来解决此问题不是很容易。
而通过分析计算表达式的值的问题,我们可以得到启发:通过将子表达式的结果逐层代入父表达式,就可以利用堆栈非常简单的解决问题,从而有以下解决方案。
public class Test2{ public static void main(String[] args) { In in=new In("D:\\expression.txt"); String string=in.readAll(); String[] strings =string.split(""); Stack<String> exprStack=new Stack<>(); for (int i = 0; i < strings.length; i++) { // 将表达式内容全部入栈 if (!strings[i].equals(")")) { exprStack.push(strings[i]); }else { // 在遇到右括号的时候将子表达式用一个String对象表示并入栈以代入父表达式 String right=exprStack.pop(); String opr=exprStack.pop(); String left=exprStack.pop(); String expr="("+left+opr+right+")";// 补全左右括号 exprStack.push(expr); } } System.out.println(exprStack.pop()); }}
上述算法关键在于将子表达式用一个String对象表示,就如同一个计算的结果,入栈后代入父表达式。
总结:将子表达式用一个结果表示,逐层代入父表达式,可以利用堆栈处理表达式的补全问题。
1 0
- 使用堆栈将缺少左括号的表达式补全并计算其值
- 利用堆栈补全表达式左括号(1309 P102)
- 将某个指定的字符串表达式转换为算术表达式并计算其结果
- 栈应用之计算全括号形式的数值表达式
- vim括号补全
- 括号补全
- latex中如何输入左括号并使右边条件对其,使用mathtype转换为latex公式
- VIM之花括号补全并格式化
- Vim大括号自动补全换行并缩进
- 有括号的算数表达式(堆栈)
- 1153 堆栈的使用 括号匹配 表达式求值 (对输入表达式的处理)
- 算法4 补全 1+2)*3-4)*5-6))) 左括号
- C语言实现括号匹配,中缀表达式转后缀表达式并计算的算法
- Oracle学习笔记 --- ORA:缺少左括号
- vim括号自动补全
- notepad++自动补全括号
- VIM括号自动补全
- VS2017关闭括号补全
- 2015 四川省赛 I Travel(bfs)
- Android Material Design的FloatingActionButton,Snackbar和CoordinatorLayout
- 最大熵模型的简单理解
- linux文件处理命令——文件处理命令
- typedef
- 使用堆栈将缺少左括号的表达式补全并计算其值
- 基础算法 KMP
- 数据结构单链表的建立的使用
- C-存储类型、初始化、链接属性的记录
- 基础算法 扩展KMP
- swift实现ios类似微信输入框跟随键盘弹出的效果
- Hibernate中的lazy(懒加载)属性
- pat1010Radix (25)
- 《深入理解Linux网络技术内幕》阅读笔记(十)