(不长,正文500字,代码70行)
最近看了点数据结构,用java写了个处理四则运算的小程序,以方便阅读的中缀表达式(就是最简单的运算式)的方式输入数据,然后输出结果,(中途输出结果还用了点lambda表达式),在这里和大家分享一下。
基本的思路如下:
步骤1 将输入的数字和运算符号依次放入栈中,其中遇到数字将其存放到数字栈中。如果遇到符号执行步骤2。
对应代码如下。
/*
······
*/
for (String t : ts) {
makestack(t);
}
/*
······
*/
static void makestack(String p) {
length++;
if (hm.get(p) != null) {
/*
······
*/
} else {
numStack.push(Double.parseDouble(p));//数字入栈
/*
······
*/
}
}
步骤2 在遇到运算符号时,进行判断:
可能1:左括号
跳过3,直接将其存到符号栈中;
可能2:右括号
执行步骤3,直到遇到左括号;
可能3:其他
执行步骤3,直到符号栈最后一个符号优先级小于当前执行的符号或者符号栈为空。
对应代码如下
if (hm.get(p) == 0) {//遇到左括号
symboStack.push(p);
} else if (hm.get(p) == 999) {//遇到右括号
while (hm.get(symboStack.lastElement()) != 0) {
simpleCalculate();
}
symboStack.pop();//此处pop的是左括号
} else {//其他运算符
while (!symboStack.isEmpty() && hm.get(p) <= hm.get(symboStack.lastElement())) {
simpleCalculate();
}
symboStack.push(p);
}
步骤3 符号栈顶弹出一个符号,当然遇到左括号则直接弹出,否则,从数字栈顶弹出两个数字,用弹出的符号进行运算,再将运算结果保存到数字栈顶。
对应simpleCalculate()方法。
步骤4 数字和符号全部输入进链表后,重复步骤3,直到符号链表为空,此时数字链表中只有一个值,这个值就是最终结果。
对应代码如下:
while (!symboStack.isEmpty()) {
simpleCalculate();
}
以下代码是可以直接再支持jdk8的环境下直接运行,如果觉得“+ - * / ^”不过瘾还可以自行再哈希图里加自定义的运算符号,以及优先级,同时再simpleCalculate()方法中定义其算法。
全部代码如下:
import java.util.HashMap;
import java.util.Stack;
public class calculate {
static Stack<Double> numStack = new Stack<Double>();
static Stack<String> symboStack = new Stack<String>();
static int n=0;
public static void main(String args[]) {
String input = "1 + ( ( 2 + 1 ) * ( 3 - 1 ) ) / ( 1 + 2 ) + 2 ^ 1";
String[] ts = input.split(" ");
for (String t : ts) {
makestack(t);
}
while (!symboStack.isEmpty()) {
simpleCalculate();
}
System.out.println("最终结果" + numStack.pop());
}
static void makestack(String p) {
if (hm.get(p) != null) {
if (hm.get(p) == 0) {
symboStack.push(p);
} else if (hm.get(p) == 999) {
while (hm.get(symboStack.lastElement()) != 0) {
simpleCalculate();
}
symboStack.pop();
} else {
while (!symboStack.isEmpty() && hm.get(p) <= hm.get(symboStack.lastElement())) {
simpleCalculate();
}
symboStack.push(p);
}
} else {
numStack.push(Double.parseDouble(p));
}
System.out.println("第" + ++n + "次入栈结果");//第n个字符的入栈结果
numStack.forEach(System.out::println);
symboStack.forEach(System.out::println);
}
static void simpleCalculate() {
String symbo = symboStack.pop();
double num2 = numStack.pop();
if (symbo.equals("+")) {
numStack.push(numStack.pop() + num2);
} else if (symbo.equals("-")) {
numStack.push(numStack.pop() - num2);
} else if (symbo.equals("*")) {
numStack.push(numStack.pop() * num2);
} else if (symbo.equals("/")) {
numStack.push(numStack.pop() / num2);
} else if (symbo.equals("^")) {
numStack.push(Math.pow(numStack.pop(), num2));
}
}
static HashMap<String, Integer> hm = new HashMap<String, Integer>() {
{
put("+", 1);
put("-", 1);
put("*", 2);
put("/", 2);
put("^", 3);
put("(", 0);
put(")", 999);
}
};
}
输出结果如下:
第1次入栈结果
1.0
第2次入栈结果
1.0
+
第3次入栈结果
1.0
+
(
第4次入栈结果
1.0
+
(
(
第5次入栈结果
1.0
2.0
+
(
(
第6次入栈结果
1.0
2.0
+
(
(
+
第7次入栈结果
1.0
2.0
1.0
+
(
(
+
第8次入栈结果
1.0
3.0
+
(
第9次入栈结果
1.0
3.0
+
(
*
第10次入栈结果
1.0
3.0
+
(
*
(
第11次入栈结果
1.0
3.0
3.0
+
(
*
(
第12次入栈结果
1.0
3.0
3.0
+
(
*
(
第13次入栈结果
1.0
3.0
3.0
1.0
+
(
*
(
第14次入栈结果
1.0
3.0
2.0
+
(
*
第15次入栈结果
1.0
6.0
+
第16次入栈结果
1.0
6.0
+
/
第17次入栈结果
1.0
6.0
+
/
(
第18次入栈结果
1.0
6.0
1.0
+
/
(
第19次入栈结果
1.0
6.0
1.0
+
/
(
+
第20次入栈结果
1.0
6.0
1.0
2.0
+
/
(
+
第21次入栈结果
1.0
6.0
3.0
+
/
第22次入栈结果
3.0
+
第23次入栈结果
3.0
2.0
+
第24次入栈结果
3.0
2.0
+
^
第25次入栈结果
3.0
2.0
1.0
+
^
最终结果5.0