4

假设我想构建一个数组来执行查找以解析网络协议(如以太网类型)。由于这样的标识符是 2 字节长,如果我使用直接索引,我最终会得到一个 2^16 单元格数组:这是一种真正的浪费,因为数组很可能是稀疏的 - 即在大批。

为了最大限度地减少内存使用量,我会使用像CMPH这样的完美哈希函数生成器,这样我就可以将我的“n”个标识符映射到一个 n 大小的数组而不会发生任何冲突。这种方法的缺点是我必须依赖外部的“公开”库。

我想知道 - 就我而言 - 是否有更聪明的方法可以在保持内存使用的同时进行恒定时间查找;请记住,我对索引 16 位无符号很感兴趣,并且设置的大小非常有限。

谢谢

4

1 回答 1

5

由于您知道您正在处理 16 位值,因此任何查找算法都将是一个恒定时间算法,因为只有 O(1) 个不同的可能值。因此,表面上可能较慢的算法(例如,线性搜索,对于 n 个元素在 O(n) 中运行)实际上可能在这里有用。

除非有一个完美的散列函数,如果你想保证快速查找,我建议你研究cuckoo hashing,它保证了最坏情况的 O(1) 查找时间并预期 O(1) 时间插入(尽管你必须是你的哈希函数有点聪明)。为 16 位值生成散列函数真的很容易;如果您计算两个 16 位乘法器并将 16 位值的高位和低位乘以这些值,然后将它们相加,我相信您会得到一个很好的散列函数 mod 任何素数。

或者,如果您不是绝对必须进行 O(1) 查找并且对预期的查找时间没有问题,您还可以使用具有开放寻址的标准哈希表,例如线性探测哈希表双哈希哈希表。使用具有这种散列方案的较小数组可能非常快,并且应该非常易于实现。

对于完全不同的方法,如果您要存储稀疏数据并希望快速查找时间,那么可能对您有效的选项是使用简单的平衡二叉搜索树。例如,treap数据结构很容易实现,并给出了预期的 O(log n) 值查找。由于您处理的是 16 位值,因此这里的 log n 约为 16(我认为对数的底数实际上有点不同),因此查找应该很快。这确实会为每个元素带来一些开销,但如果您只有几个元素,它应该很容易实现。对于更少的开销,您可能需要查看splay trees,每个元素只需要两个指针。

希望这可以帮助!

于 2012-02-08T20:27:31.457 回答