繁体   English   中英

哪个列表实现最适合从正面和背面移除和插入?

[英]Which list implementation is optimal for removing and inserting from the front and back?

我正在研究一种算法,该算法将一小组对象存储为一组较大对象的子列表。 对象本质上是有序的,因此需要有序列表。

执行的最常见操作将按频率顺序执行:

  1. 从列表中检索第n个元素(对于某些任意n)
  2. 将单个插入列表的开头或结尾
  3. 从列表中删除第一个或最后一个n个元素(对于某些任意n)

从中间移除和插入将永远不会完成,因此无需考虑其效率。

我的问题是List的实现对Java中的这个用例最有效(即LinkedList,ArrayList,Vector等)? 请通过解释不同数据结构的实现来捍卫您的答案,以便我做出明智的决定。

谢谢。

注意

不,这不是一个功课问题。 不,我没有可以为我工作的军队研究助理。

根据您的第一个标准(任意访问),您应该使用ArrayList。 ArrayLists(和一般的数组)在恒定时间内提供查找/检索。 相比之下,在LinkedList中查找项目需要线性时间。

对于ArrayLists,最后插入或删除是免费的。 它也可能与LinkedLists有关,但这将是一个特定于实现的优化(否则它是线性的)。

对于ArrayLists,前面的插入或删除需要线性时间(一致地重用空间,这些可能会变得不变,具体取决于实现)。 列表前面的LinkedList操作是不变的。

最后两个用例在某种程度上相互平衡,但最常见的情况肯定是基于阵列的存储。

至于基本的实现细节:ArrayLists基本上只是内存的连续部分。 如果你知道开头的位置,你可以只做一个添加来找到任何元素的位置。 前面的操作是昂贵的,因为可能必须移动元件以腾出空间。

LinkedLists在内存中是不相交的,由彼此链接的节点组成(引用第一个节点)。 要查找第n个节点,您必须从第一个节点开始并按照链接进行操作,直到到达所需节点。 前面的操作只需要创建一个节点并更新你的开始指针。

可能用于此目的的最佳数据结构是使用动态数组实现的双端队列 ,该动态数组基本上是一个ArrayList ,它开始将元素添加到内部数组的中间而不是开头。 不幸的是,Java的ArrayDeque不支持查找第n个元素。

但是,很容易自己实现(或查找现有的实现),然后所有三个描述的操作都可以在O(1)中完成。

如果你不担心效率,你可以用arrayList完成所有这些操作,并且最小化混乱。

如果我只插入前端或末端,我会使用某种队列或堆栈。 他们的开销最小。 或者您也可以使用链接列表。

要从第一个或最后一个中删除N个元素,我将使用链接列表,您可以删除一个节点以及之前或之后的节点。 即如果我删除前5个元素只删除第5个元素,之前的元素将消失。 此外,如果我删除最后6个元素只删除第6个到最后一个,其余的将消失。 而且java会为你做垃圾收集。 对于该操作,这将是(1)的顺序。

这是一个功课问题吗?

绝对是去LinkedList。 对于在列表的开头/结尾插入值和删除列表中的第一个/最后一个元素,它都在O(1)中运行。 这是因为需要改变以执行这些操作的所有操作只需要几个指针,这是一个成本最低的操作。

虽然ArrayLists在O(1)中检索第n个元素,而LinkedLists在O(n)中检索第n个元素,但ArrayLists在插入元素时会冒险调整它们的大小。 当为ArrayList分配的内存用完并且您尝试插入另一个元素时,您认为会发生什么? 那么发生的事情是ArrayList重复自身然后分配更多的内存(相当于它最初分配的两倍),这是一个非常昂贵的操作。 LinkedLists没有这个问题,因为所有这一切都是添加一个指针。

我对Java Vectors知之甚少,但如果它们像C ++向量一样,那么它们与ArrayLists非常相似。

我希望这有帮助。

long to Object的java.util.TreeMap,并使用i + tm.firstKey()的索引

暂无
暂无

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

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