简体   繁体   English

将现有元素添加到LinkedList之后添加新元素时的性能

[英]Performance when adding new elements after existing ones to a LinkedList

Let's assume we have a java.util.LinkedList containing a few hundreds of elements. 假设我们有一个包含数百个元素的java.util.LinkedList。 One possibility to insert a new element E after the an existing element K would be: 在现有元素K之后插入新元素E的一种可能性是:

list.add(list.indexOf(K) + 1, E);

As far as I understand this method has an O(k 2 ) behavior where k denotes the position of element K. First indexOf() runs through the list until it finds K and afterwards add has to do the same work again until it reaches position k + 1. But the entries which have to be modified could in easily be determined after the first step. 据我了解,此方法具有O(k 2 )行为,其中k表示元素K的位置。第一个indexOf()遍历列表,直到找到K,然后add必须再次执行相同的工作,直到到达位置k +1。但是在第一步之后,可以轻松确定需要修改的条目。 I think it wouldn't be that much work to create a method addAfter(K, E) with O(k) behavior. 我认为创建具有O(k)行为的方法addAfter(K,E)不需要太多工作。

Is there a way to improve the performance in a scenario like this one besides switching to java.util.ArrayList? 除了切换到java.util.ArrayList之外,还有没有办法在这种情况下提高性能?

Thank you in advance. 先感谢您。

You wrong with your assumption, that it is O(k^2), its just O(2k) which is O(k) (Btw here must be not k=index of element, but size of list, but that doesnt matter for the problem). 您的假设是错误的,它是O(k ^ 2),它的O(2k)就是O(k)(顺便说一句,这里不是k =元素的索引,而是列表的大小,但是对于问题)。 But you are right it takes twice as long and is inefficent. 但是您是对的,它需要两倍的时间并且效率低下。 The only way I can think of is to use ListIterator and find/insert yourself (which is intended to do exactly this kind of manipulations). 我能想到的唯一方法是使用ListIteratorListIterator查找/插入(旨在进行这种操作)。

As far as I understand this method has an O(k2) behavior where k denotes the position of element K. First indexOf() runs through the list until it finds K and afterwards add has to do the same work again until it reaches position k + 1. 据我了解,此方法具有O(k2)行为,其中k表示元素K的位置。第一个indexOf()遍历列表,直到找到K,然后add必须再次执行相同的工作,直到到达位置k + 1。

Actually, the cost of list.add(list.indexOf(K) + 1, E) is O(k) if list is a LinkedList . 实际上,如果listLinkedList ,则list.add(list.indexOf(K) + 1, E)的成本为O(k)

  • The list.indexOf(K) call involves k link traversals and k comparisons. list.indexOf(K)调用涉及k链接遍历和k比较。

  • The list.add(k + 1, E) call involves k + 1 link traversals. list.add(k + 1, E)调用涉及k + 1链接遍历。

Add them up - 3 k + 1 operations; 加起来3 k + 1运算; ie O(k) . O(k)


However, you are right. 但是,你是对的。 It would be possible to create an alternative version of LinkedList with an addAfter or addBefore method. 可以使用addAfteraddBefore方法创建LinkedList的替代版本。 These methods would also be O(k) but they should be faster. 这些方法也将是O(k)但是它们应该更快。 Unfortunately, LinkedList is not implemented in a way that would allow you to simply add these methods (and implement them optimally). 不幸的是, LinkedList的实现方式不允许您简单地添加这些方法(并以最佳方式实现)。 The internals of LinkedList are declared as private, so you would need to start over. LinkedList的内部被声明为私有,因此您需要重新开始。


And incidentally list.add(list.indexOf(K) + 1, E) on an ArrayList will be O(N) where N is the list length. 顺便list.add(list.indexOf(K) + 1, E) ArrayList上的list.add(list.indexOf(K) + 1, E)将是O(N) ,其中N是列表长度。 The indexOf step takes k comparisons, and the add step involves moving N - k elements. indexOf步骤进行k比较, add步骤涉及移动N - k元素。 Ergo N operations and O(N) Ergo N运算和O(N)

This sample of code is to make k operations: 此代码示例将进行k次操作:

    LinkedList<Integer> list = new LinkedList<Integer>();
    for(int i=0;i<100;i++){
        list.add(i);
    }

    Integer insert = 1001;
    Integer before = 50;
    for (ListIterator<Integer> iterator = list.listIterator(); iterator.hasNext();) {
        Integer next = iterator.next();
        if(next.equals(before)){
            iterator.add(insert);
            break;
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM