【发布时间】:2014-03-10 14:32:46
【问题描述】:
我有一小组数字,我需要经常搜索。
该组是静态的并且在开始时是已知的。
我从观察中知道,大多数时候我正在搜索的数字不在组中。
我正在寻找的是一种算法,只需一两条指令即可:
- 永远不要说某个号码不在组中,而是在组中
- 该算法大部分或所有时间都预测是否是
例如,
如果数字是 x,y,z 我可以执行以下操作:
保存:
tmp = (x | y | z)
当我搜索一个我可以做的数字时:
if ((num & tmp) == (num))
do the real search
如果数字是 x、y 或 z,则保证在与它进行 AND 时返回 num。 如果不是,我可能什么也不搜索 - 但基本上没问题。
这个测试的主要问题是大多数时候对于组中超过 5 个数字,即使 num 不在组中,我也会得到 TRUE。
我正在考虑使用 XOR 魔法:
tmp = (x ^ y ^ z)
并且在搜索时执行以下操作:
(num ^ tmp)
但我不明白这如何帮助我确定元素是否在组中。
有什么想法吗?
谢谢,
伊泰
更新
我发现有用的是使用非常简单的布隆过滤器:
我已将 x、y 和 z 散列到一个位数组(例如 8 位)。 然后,我将结果转移到正确的位:
uint8_t digest = (1 << (x % 8)) | (1 << (y % 8)) | (1 << (z % 8))
以及我使用过的搜索功能:
if ( (1 << (num % 8)) & digest )
我使用随机数进行了一些分析,发现使用 8 位在大约 30% 的时间给了我错误的指示。 使用 16 位让它变得更好。
【问题讨论】:
-
您应该提供一个或多个您需要代表的组的示例,因为这可以帮助我们找到有趣的模式。
-
你为什么不使用布尔数组查找?如果数字范围太大,可能会使用一些原始散列。
-
您是否考虑过使用例如
qsort对列表进行排序,然后使用bsearch进行搜索?您的按位算术是一个很酷的想法,但是随着您的数字列表的增长,将它们组合在一起将提供所有 1 的可能性越来越大,而且我看不到对它们进行异或运算将如何为您提供所需的结果。 -
我没有对它们进行排序的原因是该组非常小(最多 7 个数字)并且例程对性能非常敏感。这就是为什么我试图找到最快的排除检查。
-
@rcgldr 分配 528 兆字节的零,整个过程中只设置了 7 位,这是通过缓存抖动降低性能的好方法,并且可能是最慢的方法。
标签: c++ c performance algorithm