【算法与数据结构】--栈的应用-逆波兰计算器完整版代码
标签:空格 支持 boolean ret sublist replace lan efault als
逆波兰计算器完整版代码
1.将中缀表达式转为后缀表达式
2.正则表达式
3.递归调用
ReversePolishMultiCala.java代码如下:
1 import java.util.ArrayList;
2 import java.util.Collections;
3 import java.util.List;
4 import java.util.Stack;
5 import java.util.regex.Pattern;
6
7 /*
8 1.支持+-()* /
9 2.多位数,支持小数
10 3.兼容处理,过滤任何空白字符,包括空格、制表符、换页符
11 说明:逆波兰计算器完整版考虑的因素较多,下面给出完整版代码,使用:中缀表达式转后缀表达式
12 */
13
14 public class ReversePolishMultiCala{
15 /**
16 * 匹配+-* /()运算符
17 * */
18 static final String SYMBOL = "\\+|-|\\*|/|\\(|\\)";
19 //https://baijiahao.baidu.com/s?id=1636927461989417537&wfr=spider&for=pc
20 //被static关键字修饰的不需要创建对象去调用,直接根据类名就可以去访问。
21 //static可以让对象共享属性.用来修饰成员变量,将其变为类的成员,从而实现所有对象对于该成员的共享;
22 static final String LEFT = "(";
23 static final String RIGHT = ")";
24 static final String ADD = "+";
25 static final String MINUS = "-";
26 static final String TIMES = "*";
27 static final String DIVISION = "/";
28 //https://www.cnblogs.com/dolphin0520/p/3736238.html
29 //对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改;
30 //如果是引用类型的变量,则在对其初始化之后便不能再让其指向另一个对象。
31
32 /**
33 * 加减 + -
34 */
35 static final int LEVEL_01 = 1;
36 /**
37 * 乘除 * /
38 */
39 static final int LEVEL_02 = 2;
40 /**
41 * 括号
42 */
43 static final int LEVEL_HIGH = Integer.MAX_VALUE;
44
45 static Stack stack = new Stack();
46 static List data = Collections.synchronizedList(new ArrayList());
47 //要实现List的线程安全,可以使用 Collections.synchronizedList
48
49 /**
50 * 去除所有空白符
51 * @param s
52 * @return
53 */
54 public static String replaceAllBlank(String s){
55 // 正则表达式 \\s+ 匹配任何空白字符,包括空格、制表符、换页符等等,等价于[\f\n\r\t\v]
56 //replaceFirst 替换首次匹配,replaceAll 替换所有匹配。
57 return s.replaceAll("\\s+", "");
58 }
59 /**
60 * 判断是不是数字 int double long float
61 * @param s
62 * @return
63 */
64 public static boolean isNumber(String s){
65 Pattern pattern = Pattern.compile("[-\\+]?[.\\d]*$");
66 return pattern.matcher(s).matches();
67 }
68 /**
69 * 判断是不是运算符
70 * @param s
71 * @return
72 */
73 public static boolean isSymbol(String s){
74 return s.matches(SYMBOL);
75 }
76 /**
77 * 匹配运算等级
78 * @param s
79 * @return
80 */
81 public static int calcLevel(String s){
82 if("+".equals(s)||"-".equals(s)){
83 return LEVEL_01;
84 }else if("*".equals(s)||"/".equals(s)){
85 return LEVEL_02;
86 }
87 return LEVEL_HIGH;
88 }
89 /**
90 * 匹配
91 * @param s
92 * @throws Exception
93 */
94 public static List doMatch(String s) throws Exception {
95 if (s == null || "".equals(s.trim())) throw new RuntimeException("data is empty");
96 if (!isNumber(s.charAt(0) + "")) throw new RuntimeException("data illeagle, start not with a number");
97 s = replaceAllBlank(s);
98 System.out.println("doMatch s"+s);
99
100 String each;
101 int start = 0;
102
103 for (int i = 0; i ) {
104 if (isSymbol(s.charAt(i) + "")) {
105 each = s.charAt(i) + "";
106 System.out.println("eachSymbol"+each+i);
107 //栈为空,“(”操作符,或者
108 //操作符优先级大于栈顶优先级&&操作符优先级不是()的优先级,直接入栈;当遇到(时不能入栈,走else if.
109 //注意逻辑运算符的优先级,先计算&&再计算||
110 if (stack.isEmpty() || LEFT.equals(each) || calcLevel(each) > calcLevel(stack.peek())
111 && calcLevel(each) LEVEL_HIGH) {
112 System.out.println(i+"\t"+calcLevel(each)+"\t"+LEVEL_HIGH);
113 System.out.println("each"+each);
114 stack.push(each);
115 } else if (!stack.isEmpty() && calcLevel(each) calcLevel(stack.peek())) {
116 //栈非空,操作符优先级小于等于栈顶优先级时出栈入列,直到栈为空,或者遇到了(,最后操作符入栈
117 while (!stack.isEmpty() && calcLevel(each) calcLevel(stack.peek())) {
118 if (calcLevel(stack.peek()) == LEVEL_HIGH) {
119 break;
120 }
121 data.add(stack.pop());
122 }
123 stack.push(each);
124 } else if (RIGHT.equals(each)) {
125 //匹配到")"操作符,依次出栈入列直到空栈或者遇到第一个"("操作符,此时"("出栈
126 while (!stack.isEmpty() && LEVEL_HIGH >= calcLevel(stack.peek())) {
127 if (LEVEL_HIGH == calcLevel(stack.peek())) {
128 stack.pop();
129 break;
130 }
131 data.add(stack.pop());
132 }
133 }
134 start = i;
135 } else if (i == s.length() - 1 || isSymbol(s.charAt(i + 1) + "")) {
136 each = (start == 0 ? s.substring(start, i + 1) : s.substring(start + 1, i + 1));
137 System.out.println("eachNum"+each+‘\t‘+i);
138 //如果start为0,each就是将s截取(start, i + 1)
139 //substring() 方法返回字符串的子字符串。
140 if (isNumber(each)) {
141 data.add(each);
142 continue;
143 }
144 throw new RuntimeException("data not match number");
145 }
146 }
147 //如果栈里还有元素,此时元素需要依次出栈入列,可以想象栈里剩下栈顶为/,栈底为+,
148 //应该依次出栈入列,可以直接翻转整个stack添加到队列
149 Collections.reverse(stack);
150 data.addAll(new ArrayList(stack));
151
152 System.out.println("doMatch"+data);
153 return data;
154 }
155 /**
156 * 计算结果
157 * @param list
158 * @return
159 */
160 public static Double doCalc(List list){
161 Double d = 0d;
162 if(list == null || list.isEmpty()){
163 return null;
164 }
165 if(list.size() == 1){
166 //当list中只有一个元素时即是最终结果
167 System.out.println(list);
168 d = Double.valueOf(list.get(0));
169 //System.out.println(d);
170 return d;
171 }
172 ArrayList list1 = new ArrayList();
173 for(int i = 0;i){
174 list1.add(list.get(i));//获取后缀表达式列表的每一个元素并添加到新列表list1中
175 System.out.println("doCalc"+list1+i);
176 if(isSymbol(list.get(i))){
177 Double d1 = doTheMath(list.get(i-2),list.get(i-1),list.get(i));
178 list1.remove(i);//在新列表中删除第i个字符
179 list1.remove(i-1);//在新列表中删除第i-1个数字
180 list1.set(i-2,d1+"");//在新列表中用d1代替第i-2个数字
181 list1.addAll(list.subList(i+1,list.size()));//将原始列表剩下的数字和运算符添加到新列表中
182 break;
183 }
184 }
185 doCalc(list1);//递归调用此方法
186 return d;
187 }
188 /**
189 *运算
190 * @param s1
191 * @param s2
192 * @param symbol
193 * @return
194 */
195 public static Double doTheMath(String s1, String s2, String symbol){
196 Double result;
197 switch (symbol){
198 case ADD:
199 result = Double.valueOf(s1) + Double.valueOf(s2);
200 break;
201 case MINUS:
202 result = Double.valueOf(s1) - Double.valueOf(s2);
203 break;
204 case TIMES:
205 result = Double.valueOf(s1) * Double.valueOf(s2);
206 break;
207 case DIVISION:
208 result = Double.valueOf(s1) / Double.valueOf(s2);
209 break;
210 default:
211 result = null;
212 }
213 return result;
214 }
215
216 public static void main(String[] args){
217 //String math = "9+(3-1)*3+10/2";
218 String math = "12.8 + (2 - 3.55)*4+10/5.0";//8.6
219 try{
220 doCalc(doMatch(math));
221 }catch(Exception e){
222 e.printStackTrace();
223 }
224 }
225
226 }
运行结果:
1 [12.8, 2, 3.55, -, 4, *, +, 10, 5.0, /, +]
2 [8.600000000000001]
有关递归和正则表达式的内容后面继续学习,另外还有一些java的基础知识需要补充。
【算法与数据结构】--栈的应用-逆波兰计算器完整版代码
标签:空格 支持 boolean ret sublist replace lan efault als
原文地址:https://www.cnblogs.com/DJames23/p/13126458.html
评论