第3章 表、栈和队列

本文详细介绍了如何使用Java实现后缀表达式计算,包括使用栈进行运算,以及如何处理尾递归问题。同时,还提供了一个案例来说明如何使用尾递归来优化递归算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


1 LinkedList的实现数据结构是双向链表,Arraylist是单链表。

2 当直接使用Iterator(而不是通过一个增强的for循环间接使用)时,重要的是要记住一个基本法则:

如果对正在被迭代的集合进行结构上的改变(即对该集合使用add、remove或clear方法),那么迭代器就不再合法(并且在其后使用该迭代器时会有ConcurrentModificationException异常被抛出)。

为避免迭代器准备给出某一项作为下一项(next item)而该项此后或者被删除,或者也许一个新的项正好插入该项的前面这样一些讨厌的情况,有必要记住上述法则。这意味着,只要在需要立即使用一个迭代器的时候,我们才应该获取迭代器。然而,如果迭代器调用了它自己的remove方法,那么这个迭代器就仍然是合法的。 

3 尾递归涉及在最后一行的递归调用。

尾递归可以通过将代码放到一个while循环中并用每个方法参数的一次赋值代替递归调用而被手工消除。 

4 递归总能够被彻底去除(编译器是在转变成汇编语言时完成递归去除的),但是这么做是相当冗长乏味的。一般方法是要求使用一个栈,而且仅当你能够把最低限度的最小值放到栈上时这个方法才值得一用。


3.22 编写一个程序计算后缀表达式的值
一般计算使用中缀表达式: a+b
相应的前缀表达式: +ab
后缀表达式: ab+

对于一个前缀表达式的求值而言,首先要从右至左扫描表达式,从右边第一个字符开始判断,如果当前字符是数字则一直到数字串的末尾再记录下来,如果是运算符,则将右边离得最近的两个“数字串”作相应的运算,以此作为一个新的“数字串”并记录下来。一直扫描到表达式的最左端时,最后运算的值也就是表达式的值。

运用后缀表达式进行计算的具体做法:
建立一个栈S 。从左到右读表达式,如果读到操作数就将它压入栈S中,如果读到n元运算符(即需要参数个数为n的运算符)则取出由栈顶向下的n项按操作符运算,再将运算的结果代替原栈顶的n项,压入栈S中 。如果后缀表达式未读完,则重复上面过程,最后输出栈顶的数值则为结束。

    /**
     * 后缀表达式: 1+1+2*2 -----------1 1 + 2 2 * + =
     */
    private static void evalPostFix() {
        Stack<Double> s = new Stack<Double>();
        String token;
        Double a, b, result = 0.0;
        boolean isNumber;

        Scanner sc = new Scanner(System.in);
        token = sc.next();
        while (token.charAt(0) != '=') {
            try {
                isNumber = true;
                result = Double.parseDouble(token);
            } catch (Exception e) {
                isNumber = false;
                // e.printStackTrace();
            }
            if (isNumber) {
                s.push(result);
            } else {
                a = s.pop();
                b = s.pop();
                switch (token.charAt(0)) {
                    case '+':
                        s.push(a + b);
                        break;
                    case '-':
                        s.push(a - b);
                        break;
                    case '*':
                        s.push(a * b);
                        break;
                    case '/':
                        s.push(a / b);
                        break;
                    case '^':
                        s.push(Math.exp(a * Math.log(b)));
                        break;
                }
            }
            token = sc.next();
        }
        System.out.println("=========" + s.peek());
    }

3.6 M个人N次传递,求依次出局顺序
这里涉及尾递归

   /**
     * M个人从p开始N次传递,求依次出局顺序
     */
    private static void passTest() {
        int M, N, p;// M个人,从p开始,N次传递,
        M = 30;
        N = 2;
        p = 0;
        List list = new ArrayList();
        for (int i = 1; i <= M; i++) {
            list.add(i);
        }
        pass(list, N, p);// 去除list中的第N个数(N从0开始),从第p个开始
    }

    private static void pass(List list, int N, int p) {
        // 递归
//        int i = (p + N) % list.size();// 计算出要移除第几位
//        System.out.print(list.get(i) + ".");
//        list.remove(i);
//        if (list.isEmpty())
//            return;
//        pass(list, N, i);
        
        //while 
        while(!list.isEmpty()){
          int i = (p + N) % list.size();// 计算出要移除第几位
          System.out.print(list.get(i) + ".");
          list.remove(i);
          p = i;
        }
    }

3.4 有序list的交集和并集


    private static void intersectionTest() {
        List l = new ArrayList();
        List p = new ArrayList();
        List l3 = new ArrayList();
        for (int i = 0; i < 10; i++) {
            l.add(i);
        }
        p.add(1);
        p.add(3);
        p.add(4);
        p.add(7);
        p.add(10);
        p.add(12);
        intersection(l, p, l3);
    }

    private static <AnyType extends Comparable<? super AnyType>> void intersection(
            List<AnyType> L1, List<AnyType> L2, List<AnyType> L3) {
        ListIterator<AnyType> iter1 = L1.listIterator();
        ListIterator<AnyType> iter2 = L2.listIterator();

        AnyType item1 = null;
        AnyType item2 = null;
        if (iter1.hasNext() && iter2.hasNext()) {
            item1 = iter1.next();
            item2 = iter2.next();
        }
        while (item1 != null && item2 != null) {
            int compareResult = item1.compareTo(item2);
            if (compareResult == 0) {
                L3.add(item1);
                item1 = iter1.hasNext() ? iter1.next() : null;
                item2 = iter2.hasNext() ? iter2.next() : null;
            } else if (compareResult < 0) {
                // L3.add(item1);//并集
                item1 = iter1.hasNext() ? iter1.next() : null;
            } else {
                // L3.add(item2);//并集
                item2 = iter2.hasNext() ? iter2.next() : null;
            }
            // while(item1==null&&item2!=null){//并集
            // L3.add(item2);
            // item2 = iter2.hasNext() ? iter2.next() : null;
            // }
            // while(item2==null&&item1!=null){//并集
            // L3.add(item1);
            // item1 = iter1.hasNext() ? iter1.next() : null;
            // }
        }
        System.out.println(L3);
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值