使用栈,计算表达式

public class LinkedStack<T> {
    Node<T> head = new Node(null);

    public static void main(String[] args) {
        System.out.println("计算");
        /*
         * 这个程序还存在问题
         * 计算 2*3+5-5*2 正确,计算 1-2*1-2+5/2-5*2 错误
         * */
        calculation("1-2*1-2+5/2-5*2");
        calculation("2*3+5-5*2");
        /*
         * 步骤分析:
         * 1-2*1-2+5/2-5*2
         * 1-2
         * 1-2*1(* 大于 -,记录)
         * 1-2-2 (- 小于等于 *,先计算再记录 )
         * 1-0+5(在这里出错了,存在连续多个相同优先级时,计算错误)
         * */
    }

    /*
     * 这个方法的算法是:
     * 1. 规定 *(乘),/(除) 的优先级为 1,规定 +(加),-(减)的优先级为 0
     * 2. 遍历传入的字符传,若字符为操作数则入操作数栈,若字符为操作符执行 3
     * 3. 判断操作符栈是否为空,为空则直接入操作符栈,否则判断当前操作符优先级是否大于操作符栈栈顶操作符
     *    若优先级大于则入操作符栈,否则就执行 4 再入操作符栈
     * 4. 使用操作符栈栈顶的操作符计算操作数栈顶的两个操作数 num1, num2(注意操作数的顺序),然后将结果入操作数栈
     * 5. 重复 2 操作,直到字符串结束
     * 6. 重复执行 4 直到操作符栈为空,最后操作数栈唯一的元素就是结果
     *
     * */
    public static void calculation(String s) {
        LinkedStack<Double> numStack = new LinkedStack();
        LinkedStack<Character> operatorStack = new LinkedStack();

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            int priority = priority(c);
            if (priority == -1) {
                numStack.push(Double.valueOf((c + "")));
            } else {
                if (operatorStack.isEmpty()) {
                    operatorStack.push(c);
                } else {
                    if (operatorStack.priorityCompare(c) > 0) {
                        operatorStack.push(c);
                    } else {
                        /*
                         * 修复:不加 do-while 时,若两个相同优先级的运算相连,计算就会错误
                         * 如: 1-2*1-2+5/2-5*2
                         * */
                        do {
                            double num1 = numStack.pop();
                            double num2 = numStack.pop();

                            char operator = operatorStack.pop();

                            // 注意 num2, num1 顺序不可颠倒,否则 -,/ 运算会有问题
                            // calculation("2*3+5-5*2");
                            double res = calculation(operator, num2, num1);
                            numStack.push(res);
                        } while (!operatorStack.isEmpty() && operatorStack.priorityCompare(c) == 0);
                        operatorStack.push(c);
                    }
                }
            }
        }

        System.out.println("数栈");
        numStack.show();
        System.out.println("操作符栈");
        operatorStack.show();

        while (!operatorStack.isEmpty()) {
            double num1 = numStack.pop();
            double num2 = numStack.pop();

            char operator = operatorStack.pop();

            double res = calculation(operator, num2, num1);
            numStack.push(res);
        }

        System.out.println("结果:");
        numStack.show();
    }

    public static int priority(char operator) {
        switch (operator) {
            case '*':
            case '/':
                return 1;
            case '+':
            case '-':
                return 0;
            default:
                return -1;
        }
    }

    public int priorityCompare(char operatorNew) {
        char operatorOld = (char) head.getNext().getData();
        return priority(operatorNew) - priority(operatorOld);
    }

    public static Double calculation(char operator, double num1, double num2) {
        switch (operator) {
            case '*':
                return num1 * num2;
            case '/':
                return num1 / num2;
            case '+':
                return num1 + num2;
            case '-':
                return num1 - num2;
            default:
                return null;
        }
    }

    public boolean isEmpty() {
        return head.getNext() == null;
    }

    public void push(T value) {
        Node n = new Node(value);
        if (isEmpty()) {
            head.setNext(n);
        } else {
            n.setNext(head.getNext());
            head.setNext(n);
        }
    }

    public T pop() throws RuntimeException {
        if (isEmpty()) {
            throw new RuntimeException("栈空!");
        }
        Node temp = head.getNext();
        head.setNext(temp.getNext());
        return (T) temp.getData();
    }

    public void show() {
        if (isEmpty()) {
            System.out.println("栈空~~~~");
        }
        Node temp = head.getNext();
        while (temp != null) {
            System.out.println(temp);
            temp = temp.getNext();
        }
    }
}

class Node<T> {
    private T data;
    private Node next;

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    public Node(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Node{" +
                "data=" + data +
                '}';
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值