高效的数据结构,用于快速随机访问,搜索,插入和删除

时间:2009-05-20 21:28:49

标签: arrays data-structures list linked-list

我正在寻找一个数据结构(或结构),它允许我保留一个有序的整数列表,没有重复,索引和值在同一范围内。

我需要四个主要操作才能高效,按重要性粗略排列:

  1. 从给定指数中取值
  2. 查找给定值的索引
  3. 在给定索引处插入值
  4. 删除给定索引处的值
  5. 使用数组我在O(1)处有1,但是2是O(N)并且插入和删除是昂贵的(O(N),我相信)。

    链接列表有O(1)插入和删除(一旦有了节点),但1和2是O(N),从而否定了增益。

    我尝试将两个数组保持为[index] = value和b [value] = index,将1和2转换为O(1),但将3和4转换为更昂贵的操作。

    是否有更适合此的数据结构?

8 个答案:

答案 0 :(得分:13)

我会使用red-black tree将键映射到值。这为您提供了1,3(4)的O(log(n))。它还按排序顺序维护键。

对于2,我会使用哈希表将值映射到键,这样可以获得O(1)性能。它还增加了O(1)开销,用于在红黑树中添加和删除键时保持哈希表的更新。

答案 1 :(得分:4)

如何使用带二进制搜索的排序数组?

插入和删除速度很慢。但是如果您使用的是C或C ++,则可以通过调用memcpy()来优化数据是普通整数的事实。如果您知道阵列的最大大小,则甚至可以避免在使用阵列期间进行任何内存分配,因为您可以将其预分配到最大大小。

“最佳”方法取决于您需要存储的项目数量以及与查找相比需要插入/删除的频率。如果很少插入或删除带有O(1)值的排序数组肯定会更好,但如果经常插入和删除事物,二叉树可能比数组更好。对于足够小的n,阵列在任何情况下最有可能击败树。

如果关注存储大小,阵列也比树更好。树还需要为它们存储的每个项目分配内存,并且内存分配的开销可能很大,因为您只存储小值(整数)。

您可能想要分析什么是更快的,如果从排序的数组插入/删除整数,或者使用它的内存(de)分配来复制整数。

答案 2 :(得分:2)

我不知道您使用的语言是什么,但如果它是Java,您可以使用LinkedHashMap或类似的集合。它具有List和Map的所有优点,为大多数操作提供恒定的时间,并具有大象的内存占用。 :)

如果你没有使用Java,那么LinkedHashMap的想法可能仍然适用于你的问题的可用数据结构。

答案 3 :(得分:2)

使用向量进行数组访问。

使用地图作为向量中下标的搜索索引。

  • 给定下标从向量O(1)
  • 获取值
  • 给定一个键,使用地图查找值的下标。 O(LNN)
  • 插入值,按回矢量O(1)摊销,将下标插入 地图O(lnN)
  • 删除值,从地图中删除O(lnN)

答案 4 :(得分:1)

树形图怎么样? log(n)表示所描述的操作。

答案 5 :(得分:1)

我非常喜欢平衡的二叉树。它们有时比哈希表或其他结构慢,但它们更容易预测;对于所有操作,它们通常为O(log n)。我建议使用Red-black treeAVL tree

答案 6 :(得分:1)

如何用RB树实现2?我们可以让他们通过每次插入/删除操作来计算他们的孩子。这并不能使这些操作持续更长时间。然后在log n时间下来树下来找到第i个元素。但是我没有看到在java和stl。

中没有实现这个方法

答案 7 :(得分:0)

如果您在.NET中工作,那么根据MS文档http://msdn.microsoft.com/en-us/library/f7fta44c.aspx

  • SortedDictionary和SortedList都有O(log n )用于检索
  • SortedDictionary有插入和删除操作的O(log n ),而SortedList有O( n )。

两者因内存使用和插入/移除速度而异。 SortedList比SortedDictionary使用更少的内存。如果从排序数据中一次性填充SortedList,则它比SortedDictionary更快。所以这取决于哪种情况最适合你。

此外,您对链接列表的参数不是真正有效,因为它可能是插入的O(1),但您必须遍历列表才能找到插入点,所以它实际上不是。