问题:给定用户ID(整数)快速查找用户所属的组。组将包含不超过15个用户。另外,我使用libev,它无法控制传递给读I / O事件的参数,因此userID(文件描述符/整数)实际上是我可以使用的唯一的。
我的解决方案:在userID上哈希一次,进入包含groupID和userID对的哈希表。在groupID上第二次哈希到包含groupID和15个userID对的数组的哈希表。
解决方案有效,但这是服务器代码,执行次数不合时宜。我想知道双重散列效率是否低效以及是否有更好的解决方案。
答案 0 :(得分:1)
你说libev只给你一个有限数量的数据 - ev_io
句柄本身 - 并得出结论,所有文件描述符都有用。嗯,通常情况下,你可能是对的,但你可以做一个巧妙的技巧。
因为使用libev,你自己分配结构然后让libev初始化它们,没有什么能阻止你分配太多的空间。由于libev不会触及那个额外的空间,你可以将自己的东西放在那里。成功了!
那么这在实践中如何运作?您创建一个包含ev_io
作为第一个成员的新结构,然后将所有其余数据放在其后,如下所示:
struct my_mutant_io {
ev_io handle;
int group_id;
};
现在,无论您在哪里分配uv_io
,都要分配my_mutant_io
。把你的数据放在那里,但是一旦你需要将它传递给libuv函数,只需取handle
的地址:
struct my_mutant_io *mutant = malloc(sizeof(struct my_mutant_io));
if(!mutant) {
abort();
}
mutant->group_id = /* ... */;
ev_io_init(&mutant, some_callback, fd, EV_READ);
你已经给了自由ev_io
,并且它不是更明智的,它实际上只是更大结构的一部分。现在让我们继续回调。你会得到你的ev_io
,但是等一下!由于ev_io
是结构的第一个成员,因此它的地址与我们的突变体的地址相同。我们可以将ev_io *
权利转回struct my_mutant_io *
并使用它。 (只是不要告诉严格别名的神。)
像这样的结构通常被称为接力棒。
答案 1 :(得分:0)
我会在组数组中对userID进行排序,并使用二进制搜索算法。
对groupid做同样的事情,创建一个包含groupID和一组用户id的类或结构。
要创建一个组的数组并在添加它们时对它们进行排序,然后再次使用二进制搜索算法来查找该组。
编辑:
二进制搜索可能适用于少量数据,而“哈希地图”将始终与您的数据量增加相同。
所以这里是另一个问题的链接,比较了两个解决方案:Which is faster, Hash lookup or Binary search?
我必须承认你是对的!