【问题标题】:Is there a search algorithm for huge two-dimensional arrays?是否有针对大型二维数组的搜索算法?
【发布时间】:2012-05-30 13:02:56
【问题描述】:

这不是一个现实生活中的问题,它只是理论制作。

我有一个大数组,其中包含像 [1,140,245,123443] 这样的元素,所有 低选择性的整数或浮点数,唯一值个数为 10 小于数组大小的倍数。在这种情况下,B*tree 索引并不好。

我也尝试过实现位图索引,但是在 Ruby 中,二进制操作并没有那么快。

有没有什么好的算法可以搜索固定大小向量的二维数组?

而且,主要问题是,如何将向量转换为值,其中转换函数必须是单调的,所以我可以应用范围查询,例如:

(v[0]<10, v[2]>100, v[3]=32, 0.67*10^-8<v[4]<1.2154241410*10^-6)

我唯一的想法是为向量的每个组件创建单独的排序索引...然后进行二进制搜索并合并...但这是一个坏主意,因为在最坏的情况下它需要 O(N*N ) 操作...

【问题讨论】:

  • 哦,你想找到一行符合一系列条件的元素吗?是这样吗?
  • 是的,我想在 ruby​​ 上这样做)
  • 你总是可以在你的 Ruby 中添加一些 C :)

标签: ruby algorithm search multidimensional-array


【解决方案1】:

假设每个“列”模糊地均匀分布在已知范围内,您可以跟踪每列的一系列桶,以及满足桶的行列表。每列的桶数可以相同或不同,这完全是任意的。更多的桶速度更快,但会稍微占用更多的内存。

my table:
range:    {1to10} {1to4m}    {-2mto2m}
row1:     {7      3427438335 420645075}
row2:     {5      3862506151 -1555396554}
row3:     {1      2793453667 -1743457796}

buckets for column 1:
bucket{1-3} : row3
bucket{4-6} : row2
bucket{7-10} : row1

buckets for column 2:
bucket{1-2m} : 
bucket{2m-4m} : row1, row2, row4

buckets for column 3:
bucket{-2m--1m} : row2, row3
bucket{-1m-0} : 
bucket{0-1m} : 
bucket{1m-2m} : row1

然后,给定一系列标准:{v[0]&lt;=5, v[2]&gt;3*10^10},我们提取出符合该标准的 buckets

 column 1:
v[0]<=5 matches buckets {1-3} and {4-6}, which is rows 2 and 3.
 column 2:
v[2]>3*10^10} matches buckets {2m-4m} and {4-6}, which is rows 1, 2 and 3.
 column 3:
"" matches all , which is rows 1, 2 and 3.

现在我们知道我们要查找的行满足所有三个条件,因此我们列出了存储桶中匹配所有条件的所有行,在本例中为第 2 行和第 3 行。点,即使对于 大量 数据量,剩余的行数也会很少,具体取决于存储桶的粒度。您只需检查此时剩下的每一行,看看它们是否匹配。在此示例中,我们看到第 2 行匹配,但第 3 行不匹配。

这个算法技术上是O(n),但是在实践中,如果你有大量的小桶,这个算法可以非常快。

【讨论】:

  • 我不认为这是一个 O(N) 算法。例如,您需要多少操作然后您在 2 个 Nsize 数组中找到公共元素(最坏情况下最大范围查询)我认为 N*N...
  • 我不明白你在说什么。当我说它是 O(N) 时,我的意思是 N 是行数,而我忽略了列数。如果 M 是列数,则算法为 O(N*M),无论哪种方式,它的算法复杂度都与线性搜索相同。
  • 您说“现在我们知道我们正在寻找的行满足所有三个条件”......所以我们有 3 个行 ID 数组,我们必须找到它们的交集。 2 个无序数组的交集需要 size_of_first_array * size_of_first_array 操作,所以在最坏的情况下,它将需要 N*N 操作......而且我不认为桶是个好主意,最好使用 uniq 值作为键和行id 作为值。
  • @YuriBarbashov:哦,对,很好的观察。找到交点是 O(N^M),但由于有桶,它是 O((N/P)^M)(其中 N 是行数,P 是桶数,M 是列数。我不确定你说的桶是什么。每个“桶”只是一个行指针向量,因此不会占用太多空间。
  • 找到交点是 O(M*N^2)。我认为最好为 v[0] == 1 之类的查询存储像 {1 => [1,434,55], 3 => [234,555,6643] ...123 => [34,533]} 这样的索引,而不是也不利于范围查询
【解决方案2】:

使用索引:)

基本思路是将二维数组转为一维排序数组(同时保持原位置),在后面进行二分查找。

这种方法适用于任何n维数组,被数据库广泛使用,可以看作是一个可变长度的n维数组。

【讨论】:

  • 是的,正如我所说,索引数组是一维排序数组:)
  • 那么,你如何索引这种数据呢?
  • 简单数据结构:value => 原始数组中的位置列表,甚至可以是地图。
  • 问题更多是关于向量到值的转换...因为我需要通过范围查询找到所有数组元素,例如 0.67 * 10^-8
  • 你能举个例子吗?因为我不明白为什么你不能使用索引来做到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-13
  • 1970-01-01
  • 2021-12-08
  • 2021-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多