【问题标题】:Pointer into Java LinkedList Node指向 Java LinkedList 节点的指针
【发布时间】:2014-02-13 04:17:17
【问题描述】:

我在 O(1) 时将 n 个条目推送到 Java LinkedList
我想稍后在 O(1) 时删除一些独特的项目。
我想在LinkedList 处保留一个带有“指针”的数组,指向唯一节点,这样我以后可以删除它们。
有没有办法在 LinkedList 或任何其他 java 类上做到这一点?
我尝试将迭代器存储到项目中。所以我可以使用iter.remove()。但我知道当时列表上只能有一个迭代器。

我知道一个简单的解决方案可能是我自己实现链接列表。 但我宁愿使用LinkedList 或其他已经实现的Java 类。

【问题讨论】:

  • "但我知道当时列表上只能有一个迭代器。"这不是真的。
  • @LouisWasserman 即使他可以有多个迭代器,它会有帮助吗? “如果列表在迭代器创建后的任何时候在结构上被修改,除了通过Iterator 自己的删除或添加方法之外的任何方式,迭代器将抛出一个ConcurrentModificationException”。似乎如果他在一个迭代器上使用iter.remove 删除一个元素,那么其他所有元素都将变得不可用。
  • @ajb:是的,你必须通过一个迭代器来完成所有这些操作,但如果元素不连续并且你有多个要处理的元素,你就无法做到这一点。
  • @LouisWasserman “但如果元素不连续并且你有多个要处理的元素,你就无法做到这一点” - 正是这种情况。

标签: java performance pointers linked-list


【解决方案1】:

Java List 实现不提供 O(1) 删除性能*。使用迭代器,您必须遍历索引( O(n) ),使用 ArrayList 您有一个删除后移位( O(n) ),即使 LinkedList 是一个双向链表,它不会公开列表中的节点,以便您能够通过简单地重新分配下一个/最后一个引用来直接删除它们 - 需要遍历才能找到要删除的节点( O(n) )。

您可以编写自己的 MyDoublyLinkedList<MyNode<T>> 这样做,公开节点而不是其中包含的值,如果您保留对节点的引用,这将允许 O(1) 删除。索引当然是 O(n) 以通过索引从列表中获取某些内容。根据您的使用模式,这可能是一个可行的设计选择。

简而言之,如果您想使用 Java 提供的数据结构,请使用提供该性能的数据结构:

如果排序不重要并且没有重复项,请使用HashSet(但请注意,这根本不允许直接索引)

否则,重新编写代码以使用 Map 实现可能是您最好的选择。

[*] LinkedListDeque 实现是 O(1) 用于去除头部/尾部。

编辑以从 cmets 添加:

如上所述,不,没有 O(1) 时间复杂度移除操作。

这样做的原因是除了在最极端的情况下,它是无关紧要的。

在我 5 岁的 3Ghz 桌面上,通过索引(也就是说,索引 = 长度)在具有 100,000 个条目的LinkedList 上删除最坏情况 O(n) 需要 0.2 毫秒(第二点) /2)

如果我将其增加到 1,000,000 个条目,由于此框上的 Windows 内存管理,我开始遇到 Windows 交换磁盘 I/O。

简而言之,您正在尝试解决在大多数情况下不存在的问题。这通常称为“过早优化”

【讨论】:

  • 所以'Java'没有任何数据结构可以提供与简单的自写MyDoublyLinkedList<MyNode<T>>相同的性能?
  • @roy 编辑回答。
【解决方案2】:

存储指向要删除的项目的指针的问题是,从链表中删除项目还需要了解要删除的项目之前的项目。

LinkedList 不是为以低成本删除特定项目而设计的 - 您应该重新评估您使用的 List(ArrayList 在 O(1) 中删除)。你有什么理由想要一个 LinkedList 吗?

【讨论】:

  • 在 O(1) 中删除 ArrayList 是有争议的,它必须将所有内容移回原处,这已降级为本地 System.arraycopy 方法。取决于这是如何实现的,它很可能是 O(n)
  • 列表的大小n,因此最坏的情况是 O(n)。
  • 一个Arraylist 只是移动到发生成本的地方,但具有相同的性能;它不会遍历找到元素,但它必须在之后移动所有内容。两者都是 O(n)。
  • 明确地说,Java 中的LinkedList 是一个双重链表。如果您有对节点的引用,则从 dll 中删除项目是有效的;它是 O(1)。 Java 只是不允许您访问节点来这样做。
  • 大声笑,不,真的,它的 O(n) 见:stackoverflow.com/questions/2710002/… 你似乎不明白一个本地调用!= O(1)
猜你喜欢
  • 2021-02-19
  • 2019-04-19
  • 2011-07-27
  • 2014-12-13
  • 2018-09-20
  • 1970-01-01
  • 1970-01-01
  • 2012-01-14
  • 2019-03-12
相关资源
最近更新 更多