【问题标题】:LinkedList - Use Iterator for "get()" to iterate fasterLinkedList - 使用 Iterator for "get()" 更快地迭代
【发布时间】:2017-04-10 04:11:11
【问题描述】:

我正在读这本书:Data Structures and Algorithm Analysis in Java by Mark Weiss。有人可以解释一下在调用 get(i) 时使用迭代器如何减少运行时间吗?

书中的文字sn-p:

【问题讨论】:

标签: java collections linked-list iterator


【解决方案1】:
    Integer[] elements = new Integer[] { 4, 2, 7, 8, 1, 0, 3, 5, 9, 6 };

    List<Integer> arrayList = new ArrayList<>(Arrays.asList(elements));
    List<Integer> linkedList = new LinkedList<>(Arrays.asList(elements));

    for (int i = 0; i < elements.length; i++) { // Runs for O(n)
        Integer l1 = arrayList.get(i); // returns in O(1) 
        Integer l2 = linkedList.get(i); // returns in O(n)
    }

get(index) for ArrayList 直接从内存位置获取index 处的元素。
因此,get(index)O(1)

get(index) for LinkedList 通过从 LinkedList 的头部位置遍历列表来获取 index 处的元素。对于 LinkedList 的给定索引元素,没有可以预测的指定内存位置。
因此,get(index)O(n)

ArrayList 的总运行时间 = O(1) * O(n) = O(n)
LinkedList 的总运行时间 = O(n) * O(n) = O(n^2)


使用 java.util.Iterator 类

    Iterator iterator = arrayList.iterator();

    // total execution time: O(N)
    while (iterator.hasNext()) { // runs for each element iteratively
        System.out.print(iterator.next());
    }
    System.out.println();

    iterator = linkedList.iterator();

    // total execution time: O(N)
    while (iterator.hasNext()) { // runs for each element iteratively
        System.out.print(iterator.next());
    }
    System.out.println();

iterator.next() 只是迭代到List 中的下一个元素。这样做的好处是我们不需要从列表的头部搜索List NodeIterator class 可帮助您将地址保存到当前node 位置或List

同样可以使用 for-each 作为迭代器来实现,它具有更简单的代码实现。

    for (Integer I : arrayList) { // runs for each element: total execution time: O(N)
        System.out.print(I); // gets in O(1)
    }

    System.out.println();

    for (Integer I : linkedList) { // runs for each element: total execution time: O(N)
        System.out.print(I); // gets in O(1)
    }

因此使用迭代器,
ArrayList 的总运行时间 = O(n)
LinkedList 的总运行时间 = O(n)

【讨论】:

  • 我想知道......如果我声明一个迭代器,如 ListIterator k = myList.listIterator(0);和另一个'ListIterator l = myList1.listIterator(0);'并尝试做'k.intValue()+ l.intValue()'......它显示错误......它甚至显示没有'k.intValue()'可能的实现......为什么这种情况以及它与 'for(Integer I : myList)' 有何不同。
【解决方案2】:

这是因为get(i) 将从链表的头节点开始,并依次移动到下一个节点,直到它返回对ith 节点的引用,即O(n),因为它必须去通过n,或者更确切地说i 不同的节点,然后将引用返回给调用者。另一方面,迭代器将存储当前节点,并且每次对next() 的连续调用都会简单地将引用推进到直接指向当前节点之后的下一个节点,这是一个O(1) 操作。

get(i) 是通用的,并不假定您正在遍历列表,这意味着它不知道您之前查看的是哪个节点(如果有的话)。出于这个原因,它必须通过再次遍历列表的头部来重新访问ith 节点。使用迭代器假设迭代,这意味着您之前正在查看的节点,或者换句话说,您接下来要查看的节点被假设为 next 节点,因此迭代器可以优化通过存储对 current 节点的引用。这样,它就不必经过链表的头部来找到下一个节点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-16
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多