从 O(1) 中的链表中删除任何元素 - Java vs C++
Posted
技术标签:
【中文标题】从 O(1) 中的链表中删除任何元素 - Java vs C++【英文标题】:Delete any element from a linked list in O(1) - Java vs C++ 【发布时间】:2016-04-16 20:16:04 【问题描述】:在 C++ 中,我有时会将对象存储在链表中。我会将对象与指向其位置的迭代器相关联。然后,给定迭代器,我可以在 O(1) 时间内从链表中删除对象。该操作是 O(1),因为列表只是更新指向列表中前一个和下一个元素的指针。我说的C++方法:http://www.cplusplus.com/reference/list/list/erase/
有没有办法在 Java 中以相同的 O(1) 复杂度做到这一点?
LinkedList 似乎转移了后续元素:https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#remove(int)
也许有一个不同的 Java 类来实现这一点?
谢谢
【问题讨论】:
如果担心速度,请谨慎使用链表。当然,您可以轻松地插入和移除,但您所做的几乎所有其他事情都是有代价的。有时相当沉重。一方面,那些链表元素到处都是,造成了非常糟糕的局部性。 CPU 的预测和缓存能力进入了废话。 【参考方案1】:标准库LinkedList
不允许您这样做。 remove(int)
不需要移动元素,但它确实需要找到要删除的列表节点,这需要线性时间。您可以使用迭代器,但 Java 迭代器失效比 C++ 迭代器失效更具攻击性。通过位于该元素的迭代器删除一个元素后,任何其他迭代器都将失效。
您可能必须编写自己的 LinkedList
类。
【讨论】:
哦,移位元素,我的意思是它还在被删除元素之后循环遍历元素并减少它们在列表中的索引。我忘了它还会遍历列表以到达要删除的位置。所以,实际上,它循环遍历整个列表。您可以使用迭代器是什么意思?如果没有自定义 LinkedList,我认为你不能。编辑:我明白了,您可能在谈论迭代器的删除方法 @walter2011:“我的意思是它还在被删除元素之后循环遍历元素并减少它们在列表中的索引” - 它没有这样做。节点不会显式跟踪它们的索引,因此没有每个节点的索引数据需要调整。至于使用迭代器,我确实是指迭代器的remove
方法。
我想我当时解释的 javadoc 太字面意思了。它说“将任何后续元素向左移动(从它们的索引中减去一个)。”【参考方案2】:
没有人说过在链接列表中操作前一个和下一个指针需要 O(n) 时间。它正在寻找使它成为 O(n) 的元素。
如果您对列表中的每个元素都有这些“迭代器”(不是它们可能被称为的)之一,那么您仍然必须遍历这些“迭代器”中的每一个才能找到用于列表中的任何随机对象。这是一个 O(n) 操作。
一旦你找到了正确的对象,更新前一个和下一个元素不依赖于元素的数量,所以它是 O(n),与语言无关。
【讨论】:
【参考方案3】:一旦您使用迭代器找到了一个项目,您可以在其上调用remove()
并删除O(1)
中的元素,但这仅在您没有修改列表或使用支持并发更新的列表时才有效。
【讨论】:
以上是关于从 O(1) 中的链表中删除任何元素 - Java vs C++的主要内容,如果未能解决你的问题,请参考以下文章