当前位置: 代码迷 >> 综合 >> 中缀后缀(逆波兰)表达式~Java
  详细解决方案

中缀后缀(逆波兰)表达式~Java

热度:13   发布时间:2024-02-24 06:54:19.0

     中缀表达式的求值是我们人最熟悉的,但是对计算机来说却不好操作,因此,在计算结果时,往往会将中缀表达式转成其它表达式来操作(一般转成后缀表达式.)。

1、计算中缀表达式思路

      新建操作数栈和运算符栈,从头遍历表达式:

              如果是数字:

                      直接入数字栈。

              如果是符号:

                      如果运算符栈为空,直接入栈。

                      如果当前运算符优先权大于运算符栈顶元素,直接入栈。

                      如果当前运算符优先权小于或等于栈顶元素优先权,则从数栈弹出两个数,从运算符栈弹出一个运算符,进行运算,将结果入数栈,再次判断运算符栈元素优先权。

     遍历完表达式后,将数栈和运算符栈进行运算,数栈中最后保留的数字就为中缀表达式的值。

     示例代码:

public class Calculator {public static void main(String[] args) {String expression = "7*21+21*3-21*10";ArrayStack2 numStack = new ArrayStack2(10);//操作数栈ArrayStack2 operStack = new ArrayStack2(10);//符号栈int index = 0;  //表达式下标int num1 = 0;int num2 = 0;int oper = 0;int res = 0;char ch = ' ';String keepnums = "";//解析表达式while (index < expression.length()) {ch = expression.charAt(index);if (isOperate(ch)) {   //判断是否为操作符if (operStack.isEmpty()) {//判断操作符是否为空operStack.push(ch);} else {if (priority(ch) > priority(operStack.peek())) {operStack.push(ch);} else {num2 = numStack.pop();num1 = numStack.pop();oper = operStack.pop();res = cal(num1, num2, oper);numStack.push(res);operStack.push(ch);}}} else if (isNum(ch)) {   //判断是否为数字keepnums += ch;if (index == expression.length() - 1) {numStack.push(Integer.parseInt(keepnums));keepnums = "";} else {if (isOperate(expression.charAt(index + 1))) {numStack.push(Integer.parseInt(keepnums));keepnums = "";}}}++index;}//对栈内剩余数据处理while (!operStack.isEmpty()){num2 = numStack.pop();num1 = numStack.pop();oper = operStack.pop();res = cal(num1,num2,oper);numStack.push(res);}//输出结果System.out.println(expression + " = " + numStack.peek());}public static boolean isOperate(char ch) {return ch == '+' || ch == '-' || ch == '*' || ch == '/';}public static boolean isNum(char ch) {return ch >= '0' && ch <= '9';}public static int priority(int ch) {if (ch == '+' || ch == '-') {return 0;} else if (ch == '*' || ch == '/') {return 1;} else {return -1;}}public static int cal(int num1, int num2, int oper) {switch (oper) {case '+':return num1 + num2;case '-':return num1 - num2;case '*':return num1 * num2;case '/':return num1 / num2;}return 0;}
}class ArrayStack2 {private int top = -1;private int[] stack;private int maxSize = 5;public ArrayStack2() {}public ArrayStack2(int maxSize) {this.maxSize = maxSize;stack = new int[maxSize];}//判断是否已满public boolean isFull() {return (top == maxSize - 1);}//判断是否已空public boolean isEmpty() {return (top == -1);}//入栈public void push(int value) {if (isFull()) {System.out.println("栈已满!!!");return;}++top;stack[top] = value;}//出栈public int pop() {if (isEmpty()) {throw new RuntimeException("栈已空!!!");}int value = stack[top];--top;return value;}//查看栈顶元素public int peek() {if (isFull()) {throw new RuntimeException("栈已空!!!");}return stack[top];}//遍历栈public void list() {if (isEmpty()) {System.out.println("栈已空!!!");return;}int temp = top;while (temp != -1) {System.out.println(stack[temp]);--temp;}}
}

2、中缀表达式转后缀表达式思路

  1. 初始化两个栈:运算符栈s1和储存中间结果的数组s2;
  2. 从左至右扫描中缀表达式;
    1. 遇到操作数时,将其压s2;
    2. 遇到运算符时,比较其与s1栈顶运算符的优先级:
      1. 如果s1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
      2. 否则,若优先级比栈顶运算符的高,也将运算符压入s1;
      3. 否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4-1)与s1中新的栈顶运算符相比较;
    3. 遇到括号时:
      1.  如果是左括号“(”,则直接压入s1
      2.  如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃 。
  3.  重复步骤2,直到表达式的最右边 将s1中剩余的运算符依次弹出并压入s2 ,得到后缀表达式。

     示例代码后面有给出。

3、计算后缀表达式思路

      从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 和 次顶元素),并将结果入栈。重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果,前缀表达式与后缀表达式相反,计算方式是从右往左扫描。

  实例代码:

import java.util.ArrayList;
import java.util.Stack;public class PolandNotation {public static void main(String[] args) {String infixExpression = "1+((2+3)*4)-5";//将中缀表达式拆分到数组ArrayList<String> stringArrayList = getStringList(infixExpression);System.out.println(stringArrayList);//将中缀表达式转为后缀表达式ArrayList<String> postfixExpressionList = toPostfixExpression(stringArrayList);System.out.println(postfixExpressionList);//运算后缀表达式int result = calculate(postfixExpressionList);//输出结果System.out.println(infixExpression + " = " + result);}//将表达式拆分进ArrayListprivate static ArrayList<String> getStringList(String infixExpression) {ArrayList arrayList = new ArrayList();int i = 0;while (i < infixExpression.length()) {char ch = infixExpression.charAt(i);if (ch < '0' || ch > '9') {arrayList.add("" + ch);i++;} else {String num = "";while (i < infixExpression.length() && infixExpression.charAt(i) >= '0' && infixExpression.charAt(i) <= '9') {num += infixExpression.charAt(i);i++;}arrayList.add(num);}}return arrayList;}//中缀表达式转后缀表达式private static ArrayList<String> toPostfixExpression(ArrayList<String> infixExpression) {Stack<String> s1 = new Stack();  //运算符栈ArrayList<String> s2 = new ArrayList();//存储数字for (String s : infixExpression) {if (s.matches("\\d+")) {s2.add(s);} else if (s.equals("(")) {s1.add(s);} else if (s.equals(")")) {while (!s1.peek().equals("(")) {s2.add(s1.pop());}s1.pop();} else {while (s1.size() != 0 && !s1.peek().equals("(") && priority(s) <= priority(s1.peek())) {s2.add(s1.pop());}s1.push(s);}}while (s1.size() != 0) {s2.add(s1.pop());}return s2;}//计算运算符优先级private static int priority(String s) {switch (s) {case "+":return 1;case "-":return 1;case "*":return 2;case "/":return 2;}return 0;}//计算后缀表达式private static int calculate(ArrayList<String> postfixExpresson) {Stack<String> numStack = new Stack<>();for (String s : postfixExpresson) {if (s.matches("\\d+")) {numStack.push(s);} else {int num2 = Integer.parseInt(numStack.pop());int num1 = Integer.parseInt(numStack.pop());int res = 0;switch (s) {case "+":res = num1 + num2;break;case "-":res = num1 - num2;break;case "*":res = num1 * num2;break;case "/":res = num1 / num2;break;}numStack.push("" + res);}}return Integer.parseInt(numStack.pop());}
}