哪个是合适的数据结构?

时间:2011-04-24 20:38:58

标签: java algorithm data-structures

我需要一个具有以下内容的Java数据结构:

  • 快速(O(1))插入
  • 快速删除
  • 快速(O(1))max()功能

使用哪种最佳数据结构?

HashMap几乎可以工作,但使用java.util.Collections.max()至少是地图大小的O(n)。 TreeMap的插入和删除速度太慢。

有什么想法吗?

8 个答案:

答案 0 :(得分:10)

O(1)插入和O(1)max()与快速删除点互斥。

O(1)插入集合不会有O(1)max,因为集合未排序。必须对O(1)max集合进行排序,因此插入是O(n)。你必须咬紧牙关,在两者之间做出选择。然而,在这两种情况下,移除应该同样快。

如果您可以使用缓慢删除,则可以使用变量保存当前最高元素,将插入与该变量进行比较,max和insert应为O(1)。然后删除将是O(n),因为在被删除的元素最高的情况下你必须找到一个新的最高元素。

答案 1 :(得分:5)

如果可以插入和删除O(log n),则可以使用TreeSet或PriorityQueue获得O(1)最大值。对于大多数应用程序来说,O(log n)非常好。

答案 2 :(得分:4)

如果你接受O(log n)仍然是“快”,即使它不是“快(O(1))”,那么某些基于堆的优先级队列也会这样做。有关您可能使用的不同堆,请参阅comparison table

请注意,Java的库PriorityQueue不是很令人兴奋,它只保证O(n)remove(Object)

对于基于堆的队列,“remove”可以实现为“decreaseKey”,后跟“removeMin”,前提是您为此目的保留“负无穷大”值。因为这是你想要的最大值,所以在阅读文章时,将“min”的所有提及反转为“max”,将“减少”反转为“增加”......

答案 3 :(得分:2)

你不能有O(1)删除+插入+最大
证明:
假设你可以,让我们称之为数据库D.
给定阵列A:
1。将所有元素插入A到D.
2。创建空链表L.
3。 D不是空的:
3.1。 X< -D.max(); D.delete(X); --all是O(1) - 假设
3.2 L.insert_first(x) - O(1)
4。返回L.
在这里我们创建了一个O(n)的排序算法,但事实证明这是不可能的!排序称为omega(nlog(n))。矛盾!因此,D不可能存在。

答案 4 :(得分:1)

我非常怀疑TreeMap的log(n)插入和删除速度太慢 - 对于大多数实际应用程序,log(n)时间几乎是恒定的。即使你的树中有1,000,000,000个元素,如果它很平衡,你每次插入或删除时只会执行log(2,1000000000)= ~30个比较,这与其他任何哈希函数都可以进行比较。

答案 5 :(得分:0)

这样的数据结构非常棒,据我所知,不存在。其他人指出了这一点。

但是你可以超越,如果你不在乎使所有这一切变得更复杂。

如果你可以“浪费”一些记忆和一些编程工作,你可以同时使用不同的数据结构,结合每个人的专业知识。

例如,我需要排序数据结构,但希望 O(1)查找(“是集合中的元素X?”),而不是O(记录n)。我将 TreeMap HashMap (实际上不是O(1)组合在一起,但是当它不是太满时它是几乎并且哈希函数很好)我得到了很好的结果。

对于您的具体情况,我会在HashMap和自定义辅助数据结构之间进行动态组合。我脑子里有一些非常复杂的东西(哈希映射+可变长度优先级队列),但我会举一个简单的例子。只需将所有内容保留在HashMap中,然后使用仅包含地图中currentMax元素的特殊字段(max)。当您在组合数据结构中insert()时,如果您要插入的元素是&gt;比当前max,你做currentMax <- elementGoingToInsert(并将其插入HashMap)。

从组合数据结构中删除元素时,检查它是否等于currentMax,如果是,则将其从地图中删除(这是正常的),你必须找到新的{ {1}}(在O(n)中)。所以你做max

如果currentMax <- findMaxInCollection()没有经常变化,那就太好了,相信我。

但是,不要把任何事情视为理所当然。您必须努力寻找不同数据结构之间的最佳组合。进行测试,了解max变化的频率。数据结构并不容易,如果你真正合作它们而不是找到一个不存在的魔术,你可以有所作为。 :)

干杯

答案 6 :(得分:0)

这是一个堕落的答案。我注意到你没有指定你认为“快速”删除的内容;如果O(n)快,那么以下将起作用。创建一个包装HashSet的类;在插入时保持对最大元素的引用。这给出了两个恒定时间操作。对于删除,如果删除的元素是最大值,则必须遍历该集合以查找剩余元素的最大值。

这可能听起来像是一个愚蠢的答案,但在某些实际情况(概括)中,这个想法实际上可能是有用的。例如,您仍然可以在插入时以恒定时间维护五个最高值,并且每当您删除在该集合中发生的元素时,您将其从列表中删除,将其转换为进入四个列表等等;当您添加属于该范围的元素时,可以将其扩展回五。如果您通常比删除元素更频繁地添加元素,那么当您的最大值列表为空时,您可能需要提供最大值,并且可以在线性时间内恢复五个最高元素的列表。那种情况。

答案 7 :(得分:0)

正如已经解释的那样:对于一般情况,没有。但是,如果您的值范围有限,您可以使用类似计数排序的算法来获取O(1)插入,并在其上方移动最大指针的链接列表,从而实现O(1)max和删除