c - 是否可以在没有单独查找表的情况下为一组小的(<64)键创建最小完美哈希函数?

标签 c algorithm hash perfect-hash

我最近读了这篇文章Throw away the keys: Easy, Minimal Perfect Hashing关于为一组已知的键生成一个最小的完美哈希表。

这篇文章似乎假定您需要一个中间表。如果我们假设 key 集很小(即 < 64),是否还有其他更简单的方法来生成这样的函数。

在我的例子中,我想将一组线程 ID 映射到数组中的一个唯一数据 block 。线程在哈希函数生成之前启动,并在程序运行期间保持不变。线程的确切数量会有所不同,但在程序运行期间保持不变:

unsigned int thread_ids*;
unsigned int thread_count;
struct {
    /* Some thread specific data */
}* ThreadData;

int start_threads () {
    /* Code which starts the threads and allocates the threaddata. */
}

int f(thread_id) {
    /* return unique index into threadData */
}

int main() {
    thread_count = 64; /* This number will be small, e.g. < 64 */
    start_threads();
    ThreadData[f(thread_ids[0])]
}

最佳答案

是的,您可以在运行时构建最小完美哈希函数 (MPHF)。您可以使用多种算法,但其中大多数实现起来有点复杂,因此我无法为您提供有效的示例代码。许多在 cmph project 中实现.

最简单的可能是BDZ。在高层次上,查找需要计算 3 个哈希函数和 3 个内存访问。如果内存不是问题,您只需要 2 个。它支持数百万个 key 。当使用 3 个哈希函数且每个条目 2 位时,该算法需要一个大约是条目数 1.23 倍的查找表。

还有其他算法,一个是我自己发明的,the RecSplit algorithm (现在甚至有一个 research paper),还有一个 C++ implementation , 和 Java马上。基本上,算法会找到一种方法(递归地)将集合拆分为子集,直到子集大小为 1。您需要记住拆分方式。最简单的解决方案实际上是使用查找表来查找“如何拆分”,但该表非常小,64 个键可能只有 5 个整数。第一个把16分成4个子集,4个把每个子集映射到一个数字0..15。

(如果您不需要最小完美哈希函数,我添加了第二个答案,只是一个完美哈希函数。构造更简单,查找也很多更快,但需要更大的阵列。)

关于c - 是否可以在没有单独查找表的情况下为一组小的(<64)键创建最小完美哈希函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55824130/

相关文章:

c - 如何在 C 程序中从 X11 获取更新的系统 DPI 信息?

ruby - 如果键不存在创建默认值

java - 有没有更好的解决方案来获取重复项并在数组中计数?

java - 测试数字列表中的随机性

security - 如何将密码迁移到不同的散列方法

java - Java 不支持 SHA-512?

c - strtok 不断返回相同的单词

c - 字符串如何隐式类型转换为字符?

c - 以下函数的函数原型(prototype)头是什么?

algorithm - 找到边界上包含相似单元格的最大子矩阵