用于节查找的数据结构/算法

时间:2015-10-20 07:37:05

标签: algorithm

在给定每个部分的端点列表的情况下,我应该使用什么样的数据结构/算法来查找当前的部分?

例如,如果我有一个包含章节标题和内容的网页,

  • 简介(以100px结尾)
  • 第1节(以350px结束)
  • 第2节(以700px结束)
  • 结论(以1200px结束)
  • 评论

我目前处于130px,它应该返回我当前在"第1节"。

选项1

通过端点数组进行二进制搜索

from bisect import bisect_left

arr = [100, 350, 700, 1200]
pos = bisect_left(arr, 130, 0, arr[-1])

但是,对于每个位置变化,这仍然可以采用O(log n)。

选项2

当前位置的哈希表查找,

lookup = {0: "Introduction"
          1: "Introduction"
          ...
          10: "Section 1"
          11: "Section 1"
          ...
         }
section = lookup[130/10]

这很快,但浪费了很多空间

是否有处理此类问题的通用数据结构/算法?

2 个答案:

答案 0 :(得分:2)

我喜欢你的第一个选项,二进制搜索对扫描非常有效,正如你所说,第二个选项不是空间效率。

在计算机图形中缩放的传统且非常通用的解决方案是2d k-tree,它创建了一个可以通过坐标查找而不会浪费内存的树。具体来说,它的搜索,删除和插入复杂性都是O(log n),其空间复杂度为O(n)。

鉴于你只做了一个轴而且一个网页往往有1-100个部分(并且不太可能有数千个,更不用说数百万个,或者数十亿个部分),那么我个人会考虑选择简单数组,然后在有可衡量的收益/需求时转移到更复杂的k树。如果您使用C或其他语言编写此内容以便对内存布局进行一些控制,那么由于现代cpu和内存层次结构(特别是预取程序和缓存)的设计,结构数组的扫描速度会非常快。

答案 1 :(得分:0)

最简单有效的是使用具有O(LogN)复杂度的二进制搜索。

您的第二个选项具有更好的复杂度O(1),但在预填充方面具有劣势。二元搜索的预填充更加简单。

如果您不在运行时更新部分,这两种方法都是最佳的。

如果需要添加/删除/更新部分运行时,则需要数据结构。 因为您使用O(N)接近所需的更新预填充数据。这意味着更新/添加/删除部分操作最多可能需要O(N)。