用面具搜索

时间:2011-07-05 13:57:19

标签: c++ c algorithm search mask

有大量条目具有以下类型:

typedef struct {
    int value;
    int mask;
    int otherData;
} Entry;

我想根据提供的int key;尽可能快地找到此数组中的条目。需要输入以确保(key & mask) == value

这种阵列组织的最佳方式是什么,处理它的相应算法是什么?

编辑:阵列组织没有限制;它是静态的,可以在查找之前准备好。 valuemask可能包含任意值。

Edit2:valuemask可能有任意值,但数组中的条目数约为10000.因此,某些“paterns”可以提前计算。

查找次数很多。

6 个答案:

答案 0 :(得分:4)

每个位都是独立的,因此在预处理阶段[*]中,您可以对每个条目32进行分类(或者int是多大)次。每个分类存储2组:当key为0时匹配该位的那些和key为1时匹配的那些。

也就是说,如果该位的值== 1且掩码== 0,则该分类根本不存储该条目,因为它与key的任何值都不匹配(事实上,无论你使用什么方案,这些条目都应该在任何预处理阶段被删除,所以 no 分类应该存储一个条目,即使有一个位是这样的)。如果两者都为0,则存储到两个集合中。否则存入两组中的一组。

然后,根据你的密钥,你想找到一个32集的快速交集。

根据原始数组的大小,可能是存储每个集合的最佳方法是一个巨型位数组,指示数组中的每个条目是否在集合中。然后找到交叉点可以一次一个字 - &一起完成32个字,每个位数组一个。如果结果为0,继续。如果结果为非0,则表示匹配,结果中设置的位告诉您哪个条目匹配。当然,这仍然是数组大小的线性,实际上你正在进行31 &次操作来检查匹配的32个条目,这与通过原始数组的简单线性搜索大致相同。但是比较和分支的数量较少,而且您正在查看的数据压缩程度更高,因此您可能会获得更好的性能。

或者可能有更好的方法来进行交叉。

如果密钥往往被重复使用,那么您应该将查找结果缓存在从密钥到条目的映射中。如果可能的键的数量相当小(即,如果可能的输入大大少于2 ^ 32个键,和/或您有大量可用内存),那么您的预处理阶段可能只是:

  1. 轮流拍摄每个条目
  2. 找出匹配的可能密钥
  3. 将其添加到地图中以获取这些键
  4. [*]没有任何预处理,显然你所能做的就是检查每个阵列成员,直到你找到匹配或者你已经检查了所有内容。

答案 1 :(得分:2)

由于您没有额外的信息(例如,数组已排序),您需要进行线性搜索 - 遍历数组并检查条件 - 伪代码:

for( size_t index = 0; index < arraySize; index++ ) {
   if( ( array[index].mask & key ) == array[index].value ) ) {
      return index;
   }
}
return -1;

答案 2 :(得分:1)

  • 如果您有条目的地图键,那么这将非常简单。

  • 如果您的数组是按键排序的,那么您可以稍作努力进行词典二进制搜索。 [实际上,也许不是!]

  • 实际上,您只需要遍历数组,直到找到您要查找的内容。也就是说,从开始到结束迭代,并在找到它时停止。

另外,这是一个很好的例子,说明数据结构的选择如何影响算法的可用性。如果您首先选择了错误的数据结构,那么您不能仅仅针对问题抛出算法!

答案 3 :(得分:0)

线性搜索当然可行,但如果您需要使用相同的键进行多次查找,则可以尝试根据(key & mask)首先对范围进行排序。如果您只有几个固定密钥,则可以尝试使用boost.multi_index,每个密钥值都有一个索引。

答案 4 :(得分:0)

如果每个条目的mask任意变化,我看不太多 替代线性搜索。如果有重大限制 mask,这样只有少数几个值,可能会更好 对map的每个值使用某种mask,进行线性搜索 找到包含您要查找的值的第一个map。 或者,如果mask仅涉及几位,则可能值得 使用multimap,按value排序,屏蔽and全部 mask s和key索引处理相同,然后是线性的 使用完整的key进行搜索以找到完全匹配。

答案 5 :(得分:0)

如果掩码中的零位数很小,则可以复制掩码中每个“无关”位的条目。例如,如果value=0mask=0xfffe,您可以在key=0key=1的表格中输入一个条目。对于value=0mask=0xfeef,请在表格中添加4个条目:key=0x0000key=0x0010key=0x0100key=0x0110。现在,您可以对条目进行排序并使用二进制搜索,或使用二进制搜索结构,例如std::map