用栈实现四则运算

本程序先将需要运算的表达式转换成逆波兰表达式(即后缀表达式),据维基词条解释,逆波兰表示法不需要括号来标示操作符的优先级,逆波兰表达式使用栈很容易实现。

本代码已实现功能:带括号的整型表达式的四则运算(除法必须整除才符合常规想法),未实现功能:浮点计算

首先,将中缀表达式(即我们平时看到的正常表达式)转换成波兰式:

1.从左至右顺次读取表达式的字符,若是操作数加到波兰字串(用链表也可以),否则,2;

2.若操作符为‘(’或操作符栈(opS)为空,操作符入栈,否则,3;

3.若操作符为‘)’,将栈中遇到‘(’的操作符弹出并加到波兰字串尾部,将‘(’弹出(注意,此处不要追加到波

 兰字串尾部),否则,4;

4.若栈顶为‘(’,将当前操作符压栈;否则,判断栈顶操作符和当前操作符的优先级,若栈顶优先级高,弹出并追加

 到波兰字串尾部,直到栈顶优先级低于当前操作符优先级或栈为空,将当前操作符压栈,重复,1,直至表达式遍历

 完成;

5.将操作符栈中的剩余操作符弹出并追加到波兰字串尾;

其次,计算波兰表达式:

这个利用栈可以很容易就实现:从左至右遍历波兰式,遇到数字就压入操作数栈(numS),若是操作符则弹出两个操作数并进行相应计算,计算结果压入栈中,这样一轮下来,栈中只剩一个数,而这个数即为整个表达式的结果。

这里需要主要的是:

1.判断表达式的合法性,我采用的是try-catch的方法,目前还没测试出什么bug,各位如有发现的话劳烦指出,谢谢!

2.当操作数为两位以上时的处理,具体见代码

3.这里说的是四则运算,即‘+’、‘-’、‘*’、‘/’,并未考虑类似于‘-2’这种情形

下面就展示一下我的代码:

package stack;
public class BasicMath {
    char[] expch;
    private Stack<Integer> numS;
    private Stack<Character> opS;
    char[][] table = { { ' ', '+', '-', '*', '/'},
                       { '+', '>', '>', '<', '<'},
                       { '-', '>', '>', '<', '<'},
                       { '*', '>', '>', '>', '>'},
                       { '/', '>', '>', '>', '>'} };
      
    public BasicMath() {
        numS = new Stack<Integer>();
        opS = new Stack<Character>();
    }
      
    public static void main(String[] args) {
        BasicMath bm = new BasicMath();
        bm.getResult("3*(20-2)+6/2"); // test
        bm.getResult("(2+3))"); // test wrong expression
        bm.getResult("2/0"); // test divisor is zero
    }
    private char getPriority(char op1, char op2) {
        int i = 0, j = 0;
        while (i < 5) {
            if (table[i][0] == op1) {
                break;
            }
            i++;
        }
        while (j < 5) {
            if (table[0][j] == op2) {
                break;
            }
            j++;
        }
        return table[i][j];
    }
      
    // get the postfix-expression of the normal expression
    private String getRpn(String exp) {
        String rpn = "";
        expch = exp.toCharArray();
        boolean isComplete = true;
        int tmp = 0;
        for (int i = 0; i < expch.length; i++) {
            if (expch[i] >= '0' && expch[i] <= '9') {
                if(isComplete) {
                    tmp = expch[i] - 48;
                }
                else {
                    tmp = tmp * 10 + (expch[i] - 48);
                }
                isComplete = false;
            } else {
                if(!isComplete) {
                    rpn = rpn + tmp + " ";
                }
                isComplete = true;
                if (opS.isEmpty() || expch[i] == '(') {
                    opS.push(expch[i]);
                } else if (expch[i] == ')') {
                    while (!opS.isEmpty() && opS.getTop() != '(') {
                        rpn = rpn + opS.pop() + " ";
                    }
                    opS.pop();
                } else {
                    if(opS.getTop()=='(') {
                        opS.push(expch[i]);
                        continue;
                    }
                    while (!opS.isEmpty()
                            && opS.getTop()!='(' && getPriority(opS.getTop(), expch[i]) == '>') {
                        rpn = rpn + opS.pop() + " ";
                    }
                    opS.push(expch[i]);
                }
            }
        }
        if(!isComplete) {
            rpn = rpn + tmp + " ";
        } 
        while (!opS.isEmpty()) {
            rpn = rpn + opS.pop() + " ";
        }
        return rpn;
    }
    private void getResult(String exp) {
        String rpn = getRpn(exp);
        boolean isComplete = true;
        for(int i=0;i<rpn.length();i++) {
            if(rpn.charAt(i)>='0'&&rpn.charAt(i)<='9') {
                if(!isComplete) {
                    numS.push(numS.pop()*10+(rpn.charAt(i)-48));
                }
                else {
                    numS.push(rpn.charAt(i)-48);
                }
                isComplete = false;
            }
            else {
                isComplete = true;
                if(rpn.charAt(i) == ' ') {
                    ;
                }
                else {
                        numS.push(calculate(rpn.charAt(i)));
                }
            }
        }
        System.out.println(numS.pop());
    }
      
    // calculation
    private int calculate(char op) {
        try {
            int op1 = numS.pop();
            int op2 = numS.pop();
            switch(op) {
                case '+' :
                    return op2+op1;
                case '-' :
                    return op2-op1;
                case '*' :
                    return op2*op1;
                case '/' : {
                    if(op1 == 0) {
                        System.out.print("Error:The divisor should not be zero!"+" ");
                    }
                    else {
                        return op2/op1;
                    }
                }
            }
        } catch(NullPointerException e) {
            System.out.print("Error:Wrong expression" + " ");
        }
        return -1;
    }
}


你可能感兴趣的:(栈,四则运算)