将长位数组映射到查找表

Posted

技术标签:

【中文标题】将长位数组映射到查找表【英文标题】:Mapping long bit arrays to a lookup table 【发布时间】:2018-07-20 13:05:36 【问题描述】:

给定一组长度为 l (l > 64) 的 n (n

我想要达到的目标如下:

L["000010001 ... 00101010"] = 0
L["111000000 ... 01000100"] = 1
...
L["001101100 ... 01010111"] = n-1

位数组,如果转换为小数,则无序。

我目前正在使用std::unordered_map<std::bitset<81>, int> 和std::unordered_map::find,但我感觉有一种更快的方法。

【问题讨论】:

你的感觉从何而来? 根据您的解释,unordered_map 是一个不错的选择。如果我们知道更改率,或者您的应用将进行多少次查找,那么其他方法可能会更好。 “女巫是最简单的?”“更快的方法” 通常是相互排斥的。请选择一个。 Unordered_map 将从您的 bitset 的内容生成哈希,然后使用该哈希进行索引。这应该相对较快进行索引,但可能不是唯一的,具体取决于哈希的计算方式,因此可能会发生一些线性最终搜索。哈希是在插入项目时计算的,因此如果您使用 std::set,则每次 find() 调用需要进行 1000 次哈希计算,而每次调用 log2(1000)=10 次更复杂的比较。所以 std::set 在 100 find() 之后肯定会丢失 有 2^81 ~= 10^24 个不同的std::bitset<81>,但你只有 1000 个。这 10^24 个是否都是可能的值?如果没有,您可以将范围缩小到更易于管理的范围。 【参考方案1】:

std::unordered_map 具有很强的优势:它存在,已经过广泛的测试,并且已经过优化。

我能想象的唯一替代方法是在对数组(bit_pattern,index)中进行二进制搜索:对于大小小于 1000 的数组,需要少于 10 次比较。

但是...需要代码、测试和基准...

我现在的白发告诉我:如果它已经存在并且满足你的需求,那就使用它

【讨论】:

顺便说一句,由于我们正在讨论查找表,我可以放心地假设它会被写入一次并读取多次。传统的std::map 在这里会更好吗? map 是上面提到的对数组中的二分搜索 由于大小是有界的,无序映射可以初始大小来避免重新散列的需要。我不认为二分搜索会胜过它。 @Walter:不完全是。 std::map 是一个通用的二分搜索实现,而我建议一个只关注无符号整数键的自定义专用实现。 map<unsigned,whatever>有什么不同?您想使用数组而不是树?【参考方案2】:

很大程度上取决于你关心什么:

内存:可能是一个尝试 性能:用作稀疏数组的哈希集(通常比std::unordered_map 更快,并且知道输入域通常可以让您大量优化哈希函数) 如果它是结构化的,可能只是一个掩码操作

一般来说,长简单序列的索引和搜索在遗传学中得到了广泛的研究,所以也许你可以在那里找到一些算法。

【讨论】:

就我而言,一切都与性能有关。我赞成这个答案,因为你给了我一个很好的参考来开始我的研究(遗传学,优化散列函数)。 祝你好运。请记住,与减少计算次数相比,有时适合某些缓存可以为您带来更大的性能提升。

以上是关于将长位数组映射到查找表的主要内容,如果未能解决你的问题,请参考以下文章

二位数组中的查找

华为机试真题 C++ 实现查找众数及中位数

华为机试真题 C++ 实现查找众数及中位数

华为机试真题 Java 实现查找众数及中位数

剑指offer:二位数组中的查找

如何计算基于组的分位数?