O(1) 随机插入/删除和 O(1) 随机访问的数据结构是啥?

Posted

技术标签:

【中文标题】O(1) 随机插入/删除和 O(1) 随机访问的数据结构是啥?【英文标题】:What data structure for O(1) random insertion/deletion and O(1) random access?O(1) 随机插入/删除和 O(1) 随机访问的数据结构是什么? 【发布时间】:2010-01-05 11:57:56 【问题描述】:

我不知道该问题使用什么数据结构。我希望结构具有:

恒定时间插入或删除。 按 id 进行恒定时间检索。

实际系统是:

我有一堆对象,每个对象都有一个唯一的 ID。我的程序将需要接收对 id 的请求并返回相关对象。

每当它收到我想要的请求时:搜索结构以查看它是否存在。如果是,请将其退回。如果不是,则将其从磁盘加载到内存中(将其放入结构中,以便下次请求时不必使用磁盘),然后将其返回。

我正在使用 C。

这是similar question,但我不确定它的相关性。

【问题讨论】:

我认为你不是第一个想要多合一廉价数据结构的人 :-) ***.com/questions/890357/… 这也不完全一样。 是的,那里请求“快速”而不是“O(1)”(并且还请求搜索)。这些问题都不会得到确切的解决方案,但您接受此处那里接受的答案完全相同。 数组要么没有 O(1) 查找,要么没有 O(1) 插入,这取决于你是否通过数组中的索引来计算(在这种情况下没有 O(1)插入),或者通过数组中对象的某些属性(在这种情况下没有 O(1) 查找)。如果“唯一 id”位于足够小的范围内,您可以将其用作索引并预先分配“所有内容的大数组”,那么在这种情况下,您可以通过索引进行 O(1) 读/写访问,而且你不需要插入。 【参考方案1】:

在您的情况下,Hash table 可能是一个很好的解决方案——即使它不在 O(1) 中时也有冲突:这是一个非常有效的解决方案。

【讨论】:

请务必查看几个哈希表实现,以便找到满足您需求的最佳性能。如果您想了解更多信息,请不要错过有关 Google 的“BigTable”的信息。他们有一个很棒的哈希表实现。 (它实际上是一个数据库,但使用了几个 Hash Table 概念,以及一个 Hash Table 作为索引) 哈希表访问不需要使用 hash() 函数,这导致 O(THash(key))【参考方案2】:

唯一适合它的结构是... C 数组。 SomeObject arr[MAX_NUM_OBJECTS] 以快速有效的方式处理此问题

【讨论】:

等等...你在删除时的表现如何? O(1) 因为您可以通过 ID 查找 O(1) 的唯一方法是您可以使用 ID 作为数组索引 - 然后删除只是将条目设置为 null。 ++ @Michael Borgwardt:对。在ID可以作为数组索引的情况下,恒等函数是一个“完美的散列函数”。如果 ID 大于此值,您将恢复正常的散列,这也是 O(1),但可能会因相当大的常数界限而变慢。【参考方案3】:

为什么不把它们全部放在一个文件中,对文件进行映射,然后让操作系统处理缓存?

【讨论】:

这是一个很好的观点,唯一不这样做的原因是在这种情况下内存效率低下。我正在使用的对象是每个 268 字节,一页内存是 4KB。 好的,但是从磁盘读取 268 字节不一定比读取 4KB 快。【参考方案4】:

取决于数据量和键是什么。哈希表适用于难以比较的大量数据(字符串、复杂数据结构等)。对于具有整数键的较小数据集,您通常可以使用简单的红黑树获得更好的性能。这是因为好的哈希函数需要时间来执行。

实际上,这些都没有真正满足您的要求。 O(1) 访问只有在完美的散列(并且没有完美的散列)和数组中才能真正实现。同时 O(1) 插入只能在队列、出队、堆栈、链表和完美散列中进行(同样,没有散列是完美的)。

为了给你一个更好的答案,我们真的需要知道你想要完成什么。有关您将数据结构用于什么目的的更多信息会有所帮助

【讨论】:

以上是关于O(1) 随机插入/删除和 O(1) 随机访问的数据结构是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Java每日一题——>剑指 Offer II 030. 插入删除和随机访问都是 O 的容器

Java每日一题——>剑指 Offer II 030. 插入删除和随机访问都是 O 的容器

380. O 时间插入删除和获取随机元素

LeetCode - 随机集合最长的多类别子序列

题目地址(1/“>380. O 时间插入删除和获取随机元素)

算法刷题-O 时间插入删除和获取随机元素汇总区间