import java.util.ArrayList;
import java.util.List;
/**
* 后缀表达式适合计算式进行计算,但是我们需要将 中缀表达式转成 后缀表达式
* 1、初始化两个栈:运算符栈s1和存储中间结果的栈s2;
* 2、从左至右扫描中缀表达式;
* 3、遇到操作数时,将其压s2
* 4、遇到运算符时,比较其与s1栈顶运算符的优先级:
* (1)如果s1为空,或者栈顶运算符为左括号“(”,则直接将此运算符入栈;
* (2)若优先级比栈顶运算符高,也将运算符压入s1
* (3)否则,将s1栈顶的运算符弹出并压入s2中,然后再次与s1中的栈顶元素进行比较,直到当前运算符比栈顶运算符的优先级高或者栈空
* 5、遇到括号时:
* (1)如果是左括号,则直接压入s1
* (2)如果是右括号,则依次弹出栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
* 6、重复2-5,直到表达式的最右边
* 7、将s1中剩余的运算符依次弹出并压入s2
* 8、依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
*/
public class Calculator {
public static void main(String[] args) {
// String infixExpression = "1 * ( 2 + 3 - 4 * 5 ) * 6 - 7"; //测试结果为-97,正确
// String infixExpression = "1 - 2 * 3 + 7";
String infixExpression = "1 + ( ( 2 + 3 ) * 4 ) - 5";
List<String> strings = getListString(infixExpression);
System.out.println("中缀表达式转后缀表达式~~~~~~");
ArrayList<String> list = infixToPostfix(strings);
System.out.println(list);
int result = calculate(list);
System.out.println("计算结果 = " + result);
}
public static List<String> getListString(String expression) {
String[] split = expression.split(" ");
List<String> list = new ArrayList<>();
for (String item : split) {
list.add(item);
}
return list;
}
public static int calculate(List<String> list) {
ArrayStack stack = new ArrayStack(10);
for (String item : list) {
if (item.matches("\\d+")) {
stack.push(item);
} else {
int num1 = Integer.parseInt(stack.pop());
int num2 = Integer.parseInt(stack.pop());
int res = 0;
if ("+".equals(item)) {
res = num1 + num2;
} else if ("-".equals(item)) {
res = num2 - num1;
} else if ("*".equals(item)) {
res = num1 * num2;
} else if ("/".equals(item)) {
res = num2 / num1;
} else {
throw new RuntimeException("运算符号有误~");
}
stack.push("" + res);
}
}
return Integer.parseInt(stack.peek());
}
/**
* 中缀表达式转后缀表达式
*
* @param list 中缀表达式
* @return
*/
public static ArrayList<String> infixToPostfix(List<String> list) {
ArrayList<String> numStack = new ArrayList();
ArrayStack operatorStack = new ArrayStack(10);
for (String item : list) {
//如果是数字,直接加入栈numStack,否则,进行判断
if (isOperator(item)) {
//如果操作符栈为空或为左括号,直接加入
if ("(".equals(item) || operatorStack.isEmpty()) {
operatorStack.push(item);
continue;
}
//如果是右括号,一直把符号栈的内容加入numStack,直到碰到左括号后,把左括号出栈
if (")".equals(item)) {
while (!"(".equals(operatorStack.peek())) {
numStack.add(operatorStack.pop());
}
operatorStack.pop();
continue;
}
//如果当前符号优先级大于栈顶符号,直接入栈。否则,把栈顶符号加入numStack
while (!operatorStack.isEmpty() && priority(item) <= priority(operatorStack.peek())) {
numStack.add(operatorStack.pop());
}
operatorStack.push(item);
} else {
numStack.add(item);
}
}
//把符号栈中剩余的符号全部加入到numStack
while (!operatorStack.isEmpty()) {
numStack.add(operatorStack.pop());
}
return numStack;
}
public static boolean isOperator(String item) {
return "+".equals(item) || "-".equals(item) || "*".equals(item) || "/".equals(item) || "(".equals(item) || ")".equals(item) || "=".equals(item);
}
public static int priority(String item) {
if ("=".equals(item)) {
return -1;
} else if ("(".equals(item)) {
return 0;
} else if ("+".equals(item) || "-".equals(item)) {
return 1;
} else if ("*".equals(item) || "/".equals(item)) {
return 2;
} else if (")".equals(item)) {
return 3;
} else {
throw new RuntimeException("运算符有误~");
}
}
}
class ArrayStack {
public int maxSize;
public String[] stack;
public int top = -1;
public ArrayStack(int maxSize) {
this.maxSize = maxSize;
stack = new String[maxSize];
}
public boolean isFull() {
return top == maxSize - 1;
}
public boolean isEmpty() {
return top == -1;
}
public String peek() {
if (isEmpty()) {
throw new RuntimeException("栈空~");
}
return stack[top];
}
public void push(String value) {
if (isFull()) {
System.out.println("栈满");
return;
}
stack[++top] = value;
}
public String pop() {
if (isEmpty()) {
throw new RuntimeException("栈空~");
}
return stack[top--];
}
public int size() {
return top + 1;
}
public void show() {
if (isEmpty()) {
System.out.println("栈空~");
return;
}
for (int i = top; i >= 0; i--) {
System.out.printf("stack[%s]=%s\n", i, stack[i]);
}
}
}
中缀表达式转后缀表达式实现逆波兰表达式计算
最新推荐文章于 2024-04-12 09:59:55 发布