【发布时间】:2021-08-08 15:41:41
【问题描述】:
我不是数据结构专家,但据我了解,链表在大多数情况下被证明效率很低,主要是由于缓存未命中。我曾经考虑使用它们的少数原因之一是具有在恒定时间内合并/拆分其中两个的独特能力;但是该类没有提供这样的方法。
我想,好吧,我会实现自己的以满足我的需求。我希望新类遵循 Collections 框架 API,所以我让它实现和扩展与标准 LinkedList 完全相同的类。很快我意识到我只是在重新创建 LinkedList,所有这些都是毫无意义的。那时我还不如复制粘贴代码并添加我需要的方法。
同样,我找不到为什么没有这种方法的原因(除了我还远未完全掌握的线程安全性)。一切看起来都像是一个标准的链表实现,并且类似于 C++ STL 中的splice() 的方法可以放入其中。
我错过了什么吗?
LinkedList<Integer> list1 = new LinkedList();
list1.add(4);
list1.add(2);
list1.add(7);
// list1 = {4 , 2 , 7}
LinkedList<Integer> list2 = new LinkedList();
list2.add(9);
list2.add(4);
list2.add(6);
// list2 = {9 , 4 , 6}
list1.join(list2); // in O(1)
// at this point list2 should be invalidated/empty
// list1 = {4 , 2 , 7 , 9 , 4 , 6}
// list2 = {}
【问题讨论】:
-
效率高于一切?绝对不。可读性和可用性至少同样重要,尤其是对于 Java。而且您描述的操作甚至没有您想象的那么频繁(并且做“错误”的方式可能没有您想象的那么慢)。我不知道你对 HashTable 是什么意思。请注意,即使
LinkedList的作者也不会使用它(source)。ArrayListstraight up behaves better in most circumstances. -
您是否发现
LinkedList中利用链表优势的任何 方法? -
没错。更改头部不是主要优势,任何其他不在头部或尾部的更新都需要 O(n) 遍历。更糟糕的是,当通过不同的迭代器进行结构更改时,可以记住对 O(1) 插入或删除节点的引用的列表迭代器会失效。因此,维护两个或多个列表迭代器以在不遍历的情况下将元素从一个位置转移到另一个位置是行不通的。并且没有用于任何 O(1) 链接操作的专用 API。
-
@fvalasiad - 正如您所评论的,您可以创建自己的单链表或双链表实现,使用对节点的引用代替迭代器,以及几乎重复的 C++ std::list 功能.
-
我想说,
LinkedList更像是一个概念验证,以证明可以以不同于ArrayList的方式实现List(在JDK 1.2 的 Collection API 只有基于数组的Vector)。 This statement作者的都说了……
标签: java collections linked-list doubly-linked-list