【发布时间】:2010-10-24 17:11:08
【问题描述】:
如何像 C++ STL 中那样从头开始在 C 中创建 Hashmap?
将考虑哪些参数以及如何测试哈希图?例如,在您可以说您的哈希图已完成之前,您将运行的基准测试用例是什么?
【问题讨论】:
标签: c data-structures hashmap
如何像 C++ STL 中那样从头开始在 C 中创建 Hashmap?
将考虑哪些参数以及如何测试哈希图?例如,在您可以说您的哈希图已完成之前,您将运行的基准测试用例是什么?
【问题讨论】:
标签: c data-structures hashmap
好吧,如果您了解它们背后的基础知识,那应该不会太难。
通常您创建一个名为“buckets”的数组,其中包含键和值,以及用于创建链表的可选指针。
当您使用键访问哈希表时,您使用自定义哈希函数处理该键,该函数将返回一个整数。然后你取结果的模数,这就是你的数组索引或“桶”的位置。然后你用存储的密钥检查未散列的密钥,如果匹配,那么你找到了正确的位置。
否则,您遇到了“冲突”,必须爬过链表并比较键,直到匹配为止。 (注意一些实现使用二叉树而不是链表来解决冲突)。
查看这个快速哈希表实现:
【讨论】:
最佳方法取决于预期的密钥分布和数量 的碰撞。如果预计碰撞相对较少,那真的 使用哪种方法无关紧要。如果有很多碰撞 预期,那么使用哪个取决于重新散列的成本或 探测与操作可扩展的存储桶数据结构。
但这里是An Hashmap Implementation in C的源代码示例
【讨论】:
hashmap 的主要目标是存储数据集并使用唯一键提供近乎恒定的时间查找。有两种常见的 hashmap 实现方式:
如果哈希映射的哈希函数可能很差,不希望为可能未使用的插槽预先分配存储空间,或者条目可能具有可变大小,则最好使用单独的链接。即使负载因子超过 1.0,这种类型的 hashmap 也可以继续相对有效地运行。显然,每个条目都需要额外的内存来存储链表指针。
当负载因子保持在某个阈值以下(通常约为 0.7)并使用相当好的哈希函数时,使用开放寻址的哈希图具有潜在的性能优势。这是因为它们避免了潜在的缓存未命中和与链表相关的许多小内存分配,并在一个连续的、预先分配的数组中执行所有操作。迭代所有元素也更便宜。问题是使用开放寻址的哈希图必须重新分配到更大的大小并重新哈希以保持理想的负载因子,否则它们将面临显着的性能损失。它们的负载系数不可能超过 1.0。
创建哈希图时要评估的一些关键性能指标包括:
这是我制作的一个灵活的 hashmap 实现。我使用开放寻址和线性探测来解决冲突。
【讨论】:
除了简单的溢出条目链接列表之外,还有其他机制可以处理溢出,例如浪费很多内存。
使用哪种机制取决于您是否可以选择散列函数并可能选择多个(以实现例如双散列来处理冲突);如果您希望经常添加项目,或者地图在填充后是静态的;您是否打算删除项目; ...
实现这一点的最佳方法是首先考虑所有这些参数,然后不要自己编写代码,而是选择成熟的现有实现。谷歌有一些很好的实现——例如http://code.google.com/p/google-sparsehash/
【讨论】: