这是面试。 他们问我,实现自定义hashmap的好方法是什么。
我回答说,如果你有一系列说,n,元素。
您可以将单个键映射到索引%n的整数。 这将允许您将密钥存储在hashmap中。但 如果存在冲突,则可以在自定义数组中保留值列表。 现在,在自定义散列映射中使用列表的最坏情况是O(n)。 所以,我建议,我们可以在列表中使用Heap(min-heap)并调用heapify() 平衡它。这也会给登录复杂性?
我想到的另一件事是,我可以使用2-3-4节点的树,因此登录复杂性会降低。 (像B +树那样的东西)
在自定义堆实现的情况下解决冲突的更好的想法是什么?
答案 0 :(得分:1)
最常见的是通过以下方式解决hashmap冲突:
对于第一个示例,要使用值“world”存储键“hello”,您将通过哈希函数获取整数hashmap键(假设C / C ++实现):
// the following is given: that there is some object "myvalue"
// where myvalue.value = "world", and myvalue.key = "hello".
int hash_key = hash(myvalue.key); //myvalue.key = "hello", as given
然后将值插入索引hash_key
的deque元素:
hash_map[hash_key].push_back(myvalue);
其中hash_map
是您的N-index deques数组,myvalue
是要插入的对象(请注意myvalue
应将其自己的key
成员设置为“你好“所以以后可以检索。”
要在哈希映射中查找项目,请对键(“hello”)进行哈希处理,然后遍历双端队列,直到找到该项目。如果散列函数的摘要空间足够大(例如,32位无符号整数= 40亿个唯一散列结果)并且散列函数给出均匀分布,那么碰撞的几率就足够小(1 in 2 ^ 32)你的双端队列可能只有1或2个项目(即使你正在存储2 ^ 33个项目),而且更高级的结构(AVL树,RB树,等等)会使数据结构比它有所帮助减慢速度。
在碰撞之前,你几乎绝对会耗尽内存存储项目,而线性搜索的缓慢会成为一个限制因素。
(编辑添加:您不必[也不应该,对于大型哈希函数空间]预先分配整个哈希映射。也请使用deque,以便它随着数量的增长而增长哈希结果增长。)
答案 1 :(得分:1)
通常的技巧(至少,这就是Python和Java都这样做)是通过将动态数组或链接列表放在散列桶中来解决冲突,正如您所建议的那样。此外,哈希表获得一个名为最大负载因子的参数,例如, 2/3。当负载因子高于其允许的最大值(表超过2/3满)时,new hash table is allocated比原始数据大两倍,并且所有数据都被移入新哈希值表
虽然复制可能很昂贵,但其成本可能比amortized更高。