[数据结构与算法] 栈的应用:计算 2*2+(10-2)/(101-50*2)*3-2+5 表达式的值

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4289892.html

  1 import java.util.ArrayList;
  2 import java.util.List;
  3 import java.util.Stack;
  4 import java.util.regex.Matcher;
  5 import java.util.regex.Pattern;
  6
  7 public class ParseCalcMode {
  8
  9     public static List parse(String calcMode) {
 10         List elementsList = new ArrayList();
 11         Pattern p = Pattern.compile("(\\d+)|([-+*/])|([\\(\\)])");
 12
 13         Matcher m = p.matcher(calcMode);
 14         while (m.find()) {
 15             elementsList.add(m.group(0));
 16             //            System.out.println(m.groupCount());
 17         }
 18         return elementsList;
 19     }
 20
 21     /**
 22      * 进行混合运算
 23      *
 24      * @param srcStack
 25      * @return
 26      */
 27
 28     private static String calcMix(Stack srcStack) {
 29         Stack destStack = new Stack();
 30         // 否则有一个完成的带括计算式,则执行计算操作
 31         String data1;
 32         String opr;
 33         String data2;
 34         //
 35         String elem = (String) srcStack.pop();
 36
 37         // 先执行乘除表式
 38         while (!elem.equals("(")) {
 39             if ("*".equals(elem) || "/".equals(elem)) {
 40
 41                 data1 = (String) srcStack.pop();
 42                 opr = elem;
 43                 data2 = (String) destStack.pop();
 44
 45                 Stack tmpStack = new Stack();
 46                 // 如果是连续的乘除,则把连续乘除表达式存入一个临时栈中,待整个连续乘除表达时放完后计算临栈
 47                 while (!srcStack.isEmpty()
 48                         && (srcStack.peek().equals("*") || srcStack.peek().equals("/"))) {
 49                     // 第一次放时
 50                     if (tmpStack.isEmpty()) {
 51                         tmpStack.push(data2);
 52                         tmpStack.push(elem);
 53                         tmpStack.push(data1);
 54                     } else {
 55                         tmpStack.push(srcStack.pop());
 56                         tmpStack.push(srcStack.pop());
 57                     }
 58                     System.out.println("临时栈 tmpStack=" + tmpStack);
 59                 }
 60
 61                 // 如果不是连续的乘除时
 62                 if (tmpStack.isEmpty()) {
 63
 64                     switch (opr.charAt(0)) {
 65                     case ‘*‘:
 66                         destStack.push(String.valueOf(Integer.parseInt(data1)
 67                                 * Integer.parseInt(data2)));
 68                         break;
 69
 70                     case ‘/‘:
 71                         destStack.push(String.valueOf(Integer.parseInt(data1)
 72                                 / Integer.parseInt(data2)));
 73                         break;
 74                     }
 75
 76                 } else {
 77
 78                     destStack.push(calcSameLevel(tmpStack));
 79
 80                 }
 81
 82                 System.out.println("乘除计算后 destStack = " + destStack);
 83             } else {
 84                 // 如果不是乘除时直接放入目标栈中
 85                 destStack.push(elem);
 86                 System.out.println("非乘除直接放入 destStack = " + destStack);
 87             }
 88
 89             if (srcStack.isEmpty()) {
 90                 break;
 91             }
 92             elem = (String) srcStack.pop();
 93         }
 94
 95         // 如果没有加减时
 96         if (destStack.size() == 1) {
 97             return (String) destStack.pop();
 98         } else {
 99             // 后执行加减表式
100             return calcSameLevel(destStack);
101         }
102
103     }
104
105     /**
106      * 同级运算
107      *
108      * @param destStack
109      * @return
110      */
111     private static String calcSameLevel(Stack destStack) {
112         String tmpResult = null;
113         String data1;
114         String opr;
115         String data2;
116
117         while (!destStack.isEmpty()) {
118             if (tmpResult == null) {
119                 data1 = (String) destStack.pop();
120
121                 opr = (String) destStack.pop();
122
123                 data2 = (String) destStack.pop();
124
125             } else {
126                 data1 = tmpResult;
127                 opr = (String) destStack.pop();
128                 data2 = (String) destStack.pop();
129             }
130             switch (opr.charAt(0)) {
131             case ‘+‘:
132                 tmpResult = String.valueOf(Integer.parseInt(data1)
133                         + Integer.parseInt(data2));
134                 break;
135
136             case ‘-‘:
137                 tmpResult = String.valueOf(Integer.parseInt(data1)
138                         - Integer.parseInt(data2));
139                 break;
140             case ‘*‘:
141                 tmpResult = String.valueOf(Integer.parseInt(data1)
142                         * Integer.parseInt(data2));
143                 break;
144
145             case ‘/‘:
146                 tmpResult = String.valueOf(Integer.parseInt(data1)
147                         / Integer.parseInt(data2));
148                 break;
149             }
150         }
151         System.out.println("同优先级运算结果=" + tmpResult);
152         return tmpResult;
153     }
154
155     public static void main(String[] args) {
156         String str = "2*2+(10-2)/(101-50*2)*3-2+5";
157         // String str ="2*(3+2-1)";
158         List elementsList = parse(str);
159         System.out.println("组成算术表达式的各元素为=" + elementsList);
160
161         // 存入整体算术表达式各元素,在放入过程中如果遇到括号则要先计算括号里的算术式后再把计算出的结果放入栈中
162         Stack srcStack = new Stack();
163         for (int i = 0; i < elementsList.size(); i++) {
164             String elem = (String) elementsList.get(i);
165             if (elem.equals(")")) {
166                 System.out.println("遇到右括号,准备计算括号里的算术式,srcStack = " + srcStack);
167                 srcStack.push(calcMix(srcStack));
168                 System.out.println("括号里的算术式计算完毕,srcStack = " + srcStack);
169             } else {
170                 // 如果不为右括号放入栈
171                 srcStack.push(elem);
172                 System.out.println("非右括号,直接入栈 srcStack = " + srcStack);
173             }
174         }
175         System.out.println(srcStack);
176         // 所有括号里表达式计算完后计算整体算术式
177         if (srcStack.size() > 1) {
178             System.out.println("结果为=" + calcMix(srcStack));
179         } else {
180             System.out.println("结果为=" + srcStack.pop());
181         }
182     }
183 }

组成算术表达式的各元素为=[2, *, 2, +, (, 10, -, 2, ), /, (, 101, -, 50, *, 2, ), *, 3, -, 2, +, 5]
非右括号,直接入栈 srcStack = [2]
非右括号,直接入栈 srcStack = [2, *]
非右括号,直接入栈 srcStack = [2, *, 2]
非右括号,直接入栈 srcStack = [2, *, 2, +]
非右括号,直接入栈 srcStack = [2, *, 2, +, (]
非右括号,直接入栈 srcStack = [2, *, 2, +, (, 10]
非右括号,直接入栈 srcStack = [2, *, 2, +, (, 10, -]
非右括号,直接入栈 srcStack = [2, *, 2, +, (, 10, -, 2]
遇到右括号,准备计算括号里的算术式,srcStack = [2, *, 2, +, (, 10, -, 2]
非乘除直接放入 destStack = [2]
非乘除直接放入 destStack = [2, -]
非乘除直接放入 destStack = [2, -, 10]
同优先级运算结果=8
括号里的算术式计算完毕,srcStack = [2, *, 2, +, 8]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, (]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, (, 101]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, (, 101, -]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, (, 101, -, 50]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, (, 101, -, 50, *]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, (, 101, -, 50, *, 2]
遇到右括号,准备计算括号里的算术式,srcStack = [2, *, 2, +, 8, /, (, 101, -, 50, *, 2]
非乘除直接放入 destStack = [2]
乘除计算后 destStack = [100]
非乘除直接放入 destStack = [100, -]
非乘除直接放入 destStack = [100, -, 101]
同优先级运算结果=1
括号里的算术式计算完毕,srcStack = [2, *, 2, +, 8, /, 1]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, 1, *]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, 1, *, 3]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, 1, *, 3, -]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, 1, *, 3, -, 2]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, 1, *, 3, -, 2, +]
非右括号,直接入栈 srcStack = [2, *, 2, +, 8, /, 1, *, 3, -, 2, +, 5]
[2, *, 2, +, 8, /, 1, *, 3, -, 2, +, 5]
非乘除直接放入 destStack = [5]
非乘除直接放入 destStack = [5, +]
非乘除直接放入 destStack = [5, +, 2]
非乘除直接放入 destStack = [5, +, 2, -]
非乘除直接放入 destStack = [5, +, 2, -, 3]
临时栈 tmpStack=[3, *, 1]
临时栈 tmpStack=[3, *, 1, /, 8]
同优先级运算结果=24
乘除计算后 destStack = [5, +, 2, -, 24]
非乘除直接放入 destStack = [5, +, 2, -, 24, +]
非乘除直接放入 destStack = [5, +, 2, -, 24, +, 2]
乘除计算后 destStack = [5, +, 2, -, 24, +, 4]
同优先级运算结果=31
结果为=31

上面实现的有点复杂了,下面想了下使用 LinkedList 可能要简单一些

使用LinkedList实现

  1 import java.util.LinkedList;
  2 import java.util.regex.Matcher;
  3 import java.util.regex.Pattern;
  4
  5 /**
  6  * 使用 LinkedList 计算算术表达试的值
  7  * @author jzj
  8  *
  9  */
 10 public class ArithmeticCalc {
 11     /**
 12      * 提取算术表达式中的括号部分
 13      *
 14      * @param expression 算术表达式
 15      * @return
 16      */
 17     public static String bracket(String expression) {
 18         Pattern p = Pattern.compile("\\(([^\\(]+?)\\)");
 19
 20         Matcher m = p.matcher(expression);
 21
 22         if (m.find()) {
 23             return m.group(1);
 24         }
 25         else {
 26             return null;
 27         }
 28     }
 29
 30     /**
 31      * 分解算术表达式
 32      *
 33      * @param expression 算术表达式
 34      * @return
 35      */
 36     public static LinkedList parse(String expression) {
 37         LinkedList elemList = new LinkedList();
 38         //注,减号要放在第一个,放在中间时代表特殊意义
 39         Pattern p = Pattern.compile("(\\d+)|[-+*/()]");
 40
 41         Matcher m = p.matcher(expression);
 42         while (m.find()) {
 43             elemList.add(m.group(0));
 44         }
 45         return elemList;
 46     }
 47
 48     /**
 49      * 计算不带括号的算术表达式
 50      * @param expression 不带括号的算术表达式
 51      * @return String 返回计算结果
 52      */
 53     private static String caclExpression(String expression) {
 54         //分解算术表达式
 55         LinkedList linkList = parse(expression);
 56
 57         //先计算乘除
 58         for (int i = 0; i < linkList.size(); i++) {
 59             String e = (String) linkList.get(i);
 60             if ("*".equals(e) || "/".equals(e)) {
 61                 String oprData1 = (String) linkList.remove(i - 1);
 62
 63                 String opr = (String) linkList.remove(i - 1);
 64
 65                 String oprData2 = (String) linkList.remove(i - 1);
 66
 67                 //计算完成后将结果插入到原表达式所在位置
 68                 linkList.add(i - 1, cacl(oprData1, opr, oprData2));
 69
 70                 i = i - 1 - 1;//从结果位置向后计算
 71             }
 72         }
 73
 74         //再算计算加减
 75         for (int i = 0; i < linkList.size() && linkList.size() > 1; i++) {
 76             String oprData1 = (String) linkList.remove(i);
 77             String opr = (String) linkList.remove(i);
 78             String oprData2 = (String) linkList.remove(i);
 79             //计算完成后将结果插入到原表达式所在位置
 80
 81             linkList.add(i, cacl(oprData1, opr, oprData2));
 82             i = i - 1;//从结果位置向后计算
 83         }
 84
 85         return (String) linkList.get(0);
 86     }
 87
 88     /**
 89      * 两个数计算
 90      * @param oprData1 操作数一
 91      * @param opr 操作
 92      * @param oprData2 操作数二
 93      * @return String 返回计算结果
 94      */
 95     private static String cacl(String oprData1, String opr, String oprData2) {
 96         switch (opr.charAt(0)) {
 97         case ‘+‘:
 98             return String.valueOf(Integer.parseInt(oprData1)
 99                     + Integer.parseInt(oprData2));
100
101         case ‘-‘:
102             return String.valueOf(Integer.parseInt(oprData1)
103                     - Integer.parseInt(oprData2));
104         case ‘*‘:
105             return String.valueOf(Integer.parseInt(oprData1)
106                     * Integer.parseInt(oprData2));
107
108         case ‘/‘:
109             return String.valueOf(Integer.parseInt(oprData1)
110                     / Integer.parseInt(oprData2));
111         default:
112             return "";
113         }
114     }
115
116     public static void main(String[] args) {
117         String expression = "2*2+(2+5/(10-2*(1+1)*2-1))/(7-3*2)*3-2+5";
118         String bracketStr;
119         //如果算术表达式中有括号,则先计算括号中的表达式
120         while ((bracketStr = bracket(expression)) != null) {
121             String result = caclExpression(bracketStr);
122             System.out.println(bracketStr + "=" + result);
123             bracketStr = bracketStr.replaceAll("\\*", "\\\\*").replaceAll(
124                     "\\+", "\\\\+");
125             expression = expression.replaceAll("\\(" + bracketStr + "\\)",
126                     result);
127         }
128
129         System.out.println(expression + "=" + caclExpression(expression));
130     }
131 }
时间: 2024-10-07 06:30:42

[数据结构与算法] 栈的应用:计算 2*2+(10-2)/(101-50*2)*3-2+5 表达式的值的相关文章

数据结构与算法--栈、队列(队列)

Hello,everybody.我们又见面了.今天我们来学习一下队列这个数据结构,let's Go,开始我们的征程吧. 首先,举两个生活中的常见例子.相信大家,在用电脑工作娱乐时,都会碰到这样的现象.当我们点击程序或进行其他操作时,电脑处于死机状态.正当我们准备Reset时,它突然像打了鸡血似的,突然把刚才我们的操作,按顺序执行了一遍.之所以会出现这个现象,是因为操作系统的多个程序,需要通过一个管道输出,而按先后顺序排队造成的. 还有有个例子,在我们打客服热线时,有时会出现等待的现象.当其他客户

JavaScript数据结构和算法----栈

前言 栈是一种遵循后进先出(LIFO)原则的有序集合,新添加的或待删除的元素都保存在栈的末尾,称作栈顶,另外一端就叫栈底.在栈里,新元素都靠近栈顶,旧元素都接近栈底.可以想象桌上的一叠书,或者厨房里的堆放的盘子. 一.栈的创建 可以创建一个类来表示栈 //1.创建一种数据结构来保存栈里面的数据,这里选择数组 //2.声明一些栈的方法 // push(element(s)) : 添加一个或一些元素到栈顶 // pop() : 移除栈顶的元素,同时返回被移除的元素. // peek() : 返回栈顶

javascript数据结构与算法---栈

在上一遍博客介绍了下列表,列表是最简单的一种结构,但是如果要处理一些比较复杂的结构,列表显得太简陋了,所以我们需要某种和列表类似但是更复杂的数据结构---栈.栈是一种高效的数据结构,因为数据只能在栈顶添加或删除,所以这样操作很快,而且容易实现. 一:对栈的操作. 栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端陈为栈顶.比如餐馆里面洗盘子,只能先洗最上面的盘子,盘子洗完后,也只能螺到这一摞盘子的最上面.栈被称为 "后入先出"(LIFO)的数据结构. 由于栈具有后入先出的特点

数据结构与算法-栈和队列

一.简介 众所周知,线性表是数据结构的基础,通常有两种实现方式:数组和链表.栈和队列是最常用的数据结构,它们基于线性表实现. 二.栈 定义:栈是限定仅在表尾进行插入和删除操作的线性表,即FILO. 栈被经常类比于弹夹,即先被压如弹夹的子弹最后被打出.根据线性表的实现方式得知,栈的实现方式有两种:数组实现和链表实现. 栈的数组实现: package basic.data_structure.cha01; /** * 栈:先进后出(FILO),只允许在栈顶操作元素 * 栈的基本操作: * 初始化栈.

javascript数据结构与算法——栈

前言: 栈就是和列表类似的一种数据结构,不过栈的特点是'后人先出'.栈是一种高效的数据结构,因为数据只能在栈顶添加或删除,所以这样操作很快,而且容易实现. 1. 栈的介绍: 栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端被称为栈顶,另一端称为栈底.比如饭店罗盘子,只能从最上面取盘子,盘子洗干净后,也只能罗在做上面.栈被称为一种先入后出的(LIFO)的数据结构. 示意图:

15. C#数据结构与算法 -- 栈

这节我们讨论了两种好玩的数据结构,栈和队列. 什么是栈, 所谓的栈是栈(Stack)是操作限定在表的尾端进行的线性表.表尾由于要进行插入.删除等操作,所以,它具有特殊的含义,把表尾称为栈顶(Top) ,另一端是固定的,叫栈底(Bottom) .当栈中没有数据元素时叫空栈(Empty Stack).这个类似于送饭的饭盒子,上层放的是红烧肉,中层放的水煮鱼,下层放的鸡腿.你要把这些菜取出来,这就引出来了栈的特点先进后出(First in last out).   具体叙述,加下图: 栈通常记为:S=

python数据结构与算法——栈

# 栈# 其实python里面的list就可以当栈使用啦,用collections.deque也可以# 1. 入栈 list.append(item)# 2. 出栈 item = list.pop()# 3. 对于首元素出栈,还可以 item = list.pop(0) 和队列概念一样# 4. 其实还可以任意元素出栈 item = list.pop(i) 相当于删除第i个元素# 注意3,4是很耗时间的 栈可以方便用来判断一个字符串是否回文,但是要在一个长字符串中找到最大的回文一般用的数据结构是后

【数据结构与算法】时间复杂度的计算

算法时间复杂度的计算 [整理] 博客分类: 算法学习 时间复杂度算法 基本的计算步骤  时间复杂度的定义     一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数.记作T(n)=O(f(n)),称O(f(n))为算法的渐进时间复杂度(O是数量级的符号 ),简称时间复杂度. 根据定义,可以归纳出基本的计算步骤 1. 计算出基本操作的执行次

数据结构和算法-栈

栈可以分为 顺序栈: 数组实现 链式栈: 链表实现 空间复杂度 栈的空间复杂度: 有一个n个元素的栈, 在入栈和出栈过程中, 只需要存储一个临时变量存储空间, 所以空间复杂度是O(1) 并不是说栈有n个元素, 空间复杂度就是O(n), 而是指除了原本的空间外, 算法需要的额外空间 栈要满足后进先出(LIFO)的特性, 栈有以下几种方法 判断为空isEmpty 入栈push 出栈pop 返回栈顶元素peek 返回栈大小size 是否是空isEmpty 以下是使用列表来模拟栈的操作 # coding