【问题标题】:Searching huge sorted chunks of data搜索大量已排序的数据
【发布时间】:2011-07-10 17:17:17
【问题描述】:

我在磁盘中有大量数据记录,这些数据记录根据一些键按排序顺序排列。 一次将数据读入一个块(数千条记录)。 我必须搜索并显示与键匹配的所有记录。 我在想一些基于二分搜索的算法,但我这里有一些限制。

  1. 只能在一个块内从块的开头按顺序查找记录。
  2. 同一个key的记录可以跨多个block(如图-8跨)。在二进制搜索中,如果我正在加载中间块并且如果第一条记录匹配,那么我必须 扫描匹配块之前的块。

谁能帮我设计一个可以在 C++ 中工作的有效策略。使用线性搜索方法是否有效。

+---+
| 1 | Block1
| 3 |
| 3 |
| 4 |
+---+
| 4 | Block2
| 6 |
| 7 |
| 8 |
+---+
| 8 | Block3
| 8 |
| 8 |
| 8 |
+---+
| 8 | Block4
| 14|
| 15|
| 16|
+---+

【问题讨论】:

  • 你有(或者你可以预先计算)任何类型的索引结构,你可以保存在内存中吗?例如每个块的起始值。
  • 我的第一印象是二分查找可能是最好的。如果第一条记录匹配,则无论如何您都将检查前一个块,无论搜索方法如何(或者,等效地,您将匹配最后一条记录并必须检查下一个块)......我很想看看然而,其他人想出什么。
  • @Autopulated 我可以预先计算一个索引。

标签: c++ algorithm search binary-search


【解决方案1】:

您可以构建一个由每个块中的第一个条目组成的辅助数组,然后在该数组上运行二进制搜索。数组的索引应直接与块索引对应,使其成为 O(1) 查找以获取相应的块。

它将最坏的情况从 O(n) 减少到 O(logn) 并且仍然相对简单。

【讨论】:

  • 但是,您必须从磁盘加载每个块才能获得第一个条目。您可以直接对块进行二进制搜索并仅加载 log n 块。如果它会被重复搜索并且额外的数组可以存储在某个地方,那么我喜欢你的想法。
  • 我在想这个。考虑到他的块看起来是固定大小的,他可能需要在每次添加到数组时移动数据,此时他可以获得第一个条目。
【解决方案2】:

你的想法,使用二分搜索,是正确的。您可以通过在每个节点中保存最小值和最大值来一起避免线性扫描。在您的示例中,构建的二叉搜索树将如下所示:

Block1    <- (1,4)
                    (1,8)
Block2    <- (4,8)
                          (1,16)
Block3    <- (8,8)
                    (8,16)
Block4    <- (8,16)

....

同时拥有最大值和最小值使得计算更高节点的效率更高。在您的示例中,如果您想搜索“8”,您将去 ...->...->...->(1,16)->(1,8)->(4,8) ,因此您找到了正确的块,而无需向后搜索,并且以最有效的 (log(n)) 正确方式。

【讨论】:

    【解决方案3】:

    这是一个众所周知的问题,并且有一个众所周知的数据结构可以解决它,主要用于数据库中:)

    这个想法是使用B+ Tree

    这个想法是在结构顶部叠加一种二叉搜索树(除了每个节点有 2 个以上的子节点)以进行搜索。

    【讨论】:

      【解决方案4】:

      如果您对密钥分配有任何了解,您可以通过猜测要检查的第一个位置来改进二分搜索。作为示例,使用“Name”键和值“Bob”,您可以估计“B”所在的位置,或者简单地基于字母表中的位置,或者更复杂地使用键的特定领域知识(第一个的分布频率英文名字中的字符,例如)

      无论哪种方式,二分搜索都是可行的方法,可选择使用块中的第一个键预加载或缓存,如你所见。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-22
        • 2012-12-24
        • 2011-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多