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

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

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);
    }

    //将表达式拆分进ArrayList
    private 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());
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值