为查找范围内的项目优化了哪种排序数据结构?

时间:2009-04-02 22:43:05

标签: algorithm data-structures theory

假设我有一堆带日期的对象,我经常想找到两个任意日期之间的所有对象。什么样的数据结构对此有利?

5 个答案:

答案 0 :(得分:4)

假设您在按日期表示排序时,数组将执行此操作。

进行二分查找以找到> =开始日期的索引。然后,您可以进行另一次搜索,以查找指数< =结束日期,并留下偏移量&项目数量,或者如果您要处理它们,只需迭代列表直到超过结束日期。

答案 1 :(得分:4)

二叉搜索树听起来就像你正在寻找的那样。 您可以使用它来查找O(log(N)+ K)中的所有对象,其中N是对象的总数,K是实际在该范围内的对象的数量。 (只要它是平衡的)。插入/删除是O(log(N))。

大多数语言都有内置的实现。

您可以找到范围的下限(在log(n)中),然后从那里迭代,直到达到上限。

答案 2 :(得分:0)

如果没有更多细节,很难给出一个好的答案。

您需要什么样的表现?

如果线性很好,那么我只使用日期列表并遍历列表,收集范围内的所有日期。正如 Andrew Grant 建议的那样。

列表中是否有重复项?

如果您需要在集合中重复日期,那么二叉树的大多数实现可能都会出来。 Java的TreeSet之类的东西是设置实现,不允许重复元素。

有什么访问特征?很多更新的查找,反之亦然,甚至相当均匀?

大多数数据结构在查找和更新之间都需要权衡。如果您正在进行大量更新,那么针对查找进行了优化的某些数据结构将不会那么好。

那么数据结构的访问特征是什么,您需要什么样的性能,以及它必须支持哪些结构特征(例如,必须允许重复元素)?

答案 3 :(得分:0)

如果你需要进行随机访问修改:树,就像v3的答案一样。通过查找找到范围的底部,然后向上计数。插入或删除节点是O(log N)。 stbuton提出了一个很好的观点,如果你想允许重复(对于带有日期戳的事件似乎是合理的),那么你不需要基于树的集合。

如果您不需要进行随机访问修改:排序数组(或向量或其他)。通过二进制斩波找到范围起点的位置,然后向上计数。插入或删除在中间是O(N)。重复很容易。

查找的算法性能在两种情况下都是相同的,O(M + log N),其中M是范围的大小。但是阵列每个条目使用的内存更少,并且可能更快地计算整个范围,因为在二进制斩波之后它只是前向顺序内存访问而不是跟随指针。

在这两种情况下,您可以安排最后插入(摊销)O(1)。对于树,保留头部末端元素的记录,然后得到O(1)界限。对于数组,以指数方式增长它并且你得到摊销O(1)。如果您所做的更改总是或几乎总是“使用当前时间添加新事件”,这很有用,因为时间(您希望)是一个非减少数量。如果您正在使用系统时间,那么当然您必须检查,以避免在时钟向后重置时发生意外。

替代答案:一个SQL表,让数据库优化它想要的方式。谷歌的BigTable结构专门设计用于快速查询,确保任何查询的结果始终是来自预先准备的索引的连续序列: - )

答案 4 :(得分:-1)

您需要一种结构,使您可以按日期对对象进行排序,无论何时插入或删除新对象,以及在给定日期之后或之前查找所有对象的分段的边界都很容易。

heap似乎是完美的候选人。在实际应用中,堆简单地由数组表示,其中所有对象按顺序存储。将排序的数组看作堆只是一种在正确的位置和O(log(n))中插入新对象和删除的方法。

当你必须找到日期A(被排除的)和B(包括)之间的所有对象时,找到A的位置(或插入位置,即前面元素的位置)比A)晚,以及B的位置(或B的插入位置),并返回那些位置之间的所有对象(这只是数组/堆中那些位置之间的部分)