最近看数据结构,看到栈和后缀表达式的地方,于是自己动手用写了一段很简单的实现计算String类型的四则运算的例子。
思路:给一个String类型的算术计算式,求这个String算数式的值。计算String串的值,涉及到一个主要问题:加减乘除及括号的优先级该怎么解决。于是后缀表达式就华丽丽的登场了,它涉及到的数据结构是栈,然后利用后缀表达式计算。
首先中缀转后缀:运算时从左向右开始,1)如果是数字直接输出;2)如果是'(',则直接入栈;3)如果是运算符,先与栈顶元素比较优先级,优先级大于或等于栈顶元素直接入栈,小于栈顶元素优先级则栈顶元素先出栈,之后再与栈顶元素优先级比较,重复3)规则;4)如果是')',则将栈中元素持续出栈,直到'('元素出栈,然后继续按规则1、2、3、4执行。比如9+(3-1)*3-10/2中缀表达式转完后缀表达式为:9 3 1 - 3 * 10 2 / - +
中缀转弯后缀表达式之后就该计算了,将后缀表达式依次入栈,数字直接入栈,运算符不入栈,有运算符时连续弹出2个元素计算后将结果入栈。比如上面的后缀表达式,9先入栈,之后3入栈,之后1入栈,之后为‘-’,则不入栈,先将栈顶的1取出作为被减数(位置要正确,先取出的元素位于运算符右侧),再将3取出作为减数,结果为2,然后将2入栈,按规则一步一步来即可得到结果。下面是我这段时间写的一个小程序,暂时只能运算整数的四则运算,之后有时间了我会慢慢完善。
class D1 implements Serializable {
    public static void main(String[] args) {
        //这里做测试
        D1 d = new D1();
        String str = "9+(3-1)*3-10/2";
        List<String> list = d.infixToSuffix(str);
        Integer num = d.getReslut(list);
        System.out.println(num);
    }

    /**
     * 传入转换完毕的后缀表达式,计算
     * @param list
     * @return
     */
    public Integer getReslut(List<String> list){
        Integer n1 = null;
        Integer n2 = null;
        Integer reslut = null;
        Deque<Integer> opt = new LinkedList<Integer>();
        for(int i=0;i<list.size();i++){
            String num = list.get(i);
            try {
                Integer n = Integer.valueOf(num);
                opt.offerFirst(n);
            }catch (Exception e){
                n2 = opt.pollFirst();
                n1 = opt.pollFirst();
                if("+".equals(num)){
                    reslut = n1 + n2;
                }else if("-".equals(num)){
                    reslut = n1 - n2;
                }else if("*".equals(num)){
                    reslut = n1 * n2;
                }else if("/".equals(num)){
                    reslut = n1 / n2;
                }
                opt.offerFirst(reslut);
            }
        }

        return  opt.pollFirst();
    }




    //9+(3-1)*3-10/2 = 10
    //  9 3 1 - 3 * 10 2 / - +
    /**
     * 中缀表达式转后缀表达式,直接传入算数式
     * @param str
     * @return
     */
    public List<String> infixToSuffix(String str) {
        List<String> numlist = getNums(str);
        List<String> list = new ArrayList<String>();
        Deque<String> deque = new LinkedList<String>();
        for (int i = 0; i < numlist.size(); i++) {
//            Character c = str.charAt(i);
            String num = numlist.get(i);
            if("(".equals(num)||"*".equals(num)||"/".equals(num)){
                deque.offerFirst(num);
            }else if("+".equals(num)||"-".equals(num)){
                addAndMul(deque, num, list);
            }else if(")".equals(num)){
                rightKuo(deque, num, list);
            }else{
                list.add(num);
            }
            if (i == numlist.size() - 1) {
                while (true) {
                    String next = deque.pollFirst();
                    if (null == next) {
                        break;
                    }
                    list.add(next);
                }
            }
        }
        return list;
    }

    private void addAndMul(Deque<String> deque, String c, List<String> list) {
        while (true) {
            String    next = deque.peekFirst();
            if (null == next || "+".equals(next) || "-".equals(next) || "(".equals(next)) {
                deque.offerFirst(c);
                break;
            }
            list.add(deque.pollFirst());
        }
    }
    private void rightKuo(Deque<String> deque, String c, List<String> list) {
        while (true) {
            String next = deque.pollFirst();
            if ("(" .equals(next)) {
                break;
            }
            list.add(next.toString());
        }
    }
    /**
     * 将String类型算数表达式转换为list,将数字与运算符分开
     * @param str
     * @return
     */
    private List<String> getNums(String str) {
        String nums = "0123456789";
        String opts = "()+-*/";
//        String[] ss = new String[str.length()];
        List<String> list = new ArrayList<String>();
        int j = 0;
        for (int i = 0; i < str.length(); i++) {
            if (i == 0) {
//                ss[j] = str.substring(i, i + 1);
                list.add(str.substring(i, i + 1));
            } else {
                String per = str.substring(i - 1, i);
                String now = str.substring(i, i + 1);
                if(opts.indexOf(now)>-1 ){
                    j++;
//                    ss[j] = now;
                    list.add(now);
                }else if(nums.indexOf(now)>-1){
                    if(nums.indexOf(per)>-1){
//                        ss[j]=ss[j]+now;
                        list.set(j,list.get(j)+now);
                    }else{
                        j++;
//                        ss[j] = now;
                        list.add(now);
                    }
                }
            }
        }
        return list;
    }
}

以上就是这个的应用了,不想自己写栈了,于是就用了java自带的双端队列,只是使用了其中的栈的功能,其中不完善的地方之后再改了,现在就先到这里了。