我在磁盘中有大量的数据记录,这些记录按照某些键排序。 数据一次被读入一个块(数千条记录)。 我必须搜索并显示与键匹配的所有记录。 我在想一些基于二进制搜索的算法,但我在这里有一些限制。
有人可以帮助我设计一个可以在C ++中运行的有效策略。使用线性搜索方法是否有效。
+---+
| 1 | Block1
| 3 |
| 3 |
| 4 |
+---+
| 4 | Block2
| 6 |
| 7 |
| 8 |
+---+
| 8 | Block3
| 8 |
| 8 |
| 8 |
+---+
| 8 | Block4
| 14|
| 15|
| 16|
+---+
答案 0 :(得分:4)
您的想法,使用二进制搜索,是正确的。您可以通过保存每个节点中的最小值和最大值来完全避免线性扫描。在您的示例中,构造的二元搜索树将如下所示:
Block1 <- (1,4)
(1,8)
Block2 <- (4,8)
(1,16)
Block3 <- (8,8)
(8,16)
Block4 <- (8,16)
....
同时具有最大值和最小值可以有效地计算更高的节点。在您的示例中,如果您要搜索“8”,您将进入...-&gt; ...-&gt; ...-&gt;(1,16) - &gt;(1,8) - &gt; (4,8),所以你找到了正确的块,而没有向后寻求并以最有效(log(n))正确的方式。
答案 1 :(得分:4)
您可以构建一个辅助数组,该数组由每个块中的第一个条目组成,然后在该数组上运行二进制搜索。数组的索引应直接与块索引对应,使其成为O(1)查找以获得相应的块。
它将最坏的情况从O(n)切换到O(logn),并且仍然相对简单。
答案 2 :(得分:2)
这是一个众所周知的问题,有一个众所周知的数据结构可以解决它,主要用于数据库:)
我们的想法是使用B+ Tree。
这个想法是在结构的顶部叠加一种二进制搜索树(除了每个节点有超过2个子节点)以进行搜索。
答案 3 :(得分:1)
如果您对密钥分发有任何想法,可以通过猜测要检查的第一个位置来改进二进制搜索。作为样本,使用“名称”键和值“Bob”,您可以近似“B”所在的位置,或者简单地基于字母表中的位置,或者更复杂地使用关键字的特定领域知识(首先是分配频率)英文名字中的字符例如)
无论哪种方式,二进制搜索都是可行的方式,可选择使用第一个键入块预加载或缓存 - 就像你看到它们一样。