Data structures 自定义hasmap实现中的冲突解决技术

Data structures 自定义hasmap实现中的冲突解决技术,data-structures,hashmap,Data Structures,Hashmap,这是一次面试。 他们问我什么是实现自定义hashmap的好方法 我回答说,如果你有一个数组,比如说,n,元素 您可以将单个键映射到索引%n的整数。 这将允许您将密钥存储在hashmap中。但是 如果发生冲突,则可以在自定义数组中保留一个值列表。 现在,像这样在自定义hashmap中使用列表的最坏情况是O(n)。 因此,我建议,我们可以在列表中使用Heap(minheap)并调用heapify() 平衡它。这也会给logn带来复杂性 我想到的另一件事是,我可以使用一个有2-3-4个节点的树,这样l

这是一次面试。 他们问我什么是实现自定义hashmap的好方法

我回答说,如果你有一个数组,比如说,n,元素

您可以将单个键映射到索引%n的整数。 这将允许您将密钥存储在hashmap中。但是 如果发生冲突,则可以在自定义数组中保留一个值列表。 现在,像这样在自定义hashmap中使用列表的最坏情况是O(n)。 因此,我建议,我们可以在列表中使用Heap(minheap)并调用heapify() 平衡它。这也会给logn带来复杂性

我想到的另一件事是,我可以使用一个有2-3-4个节点的树,这样logn的复杂性就会降低。(有点像B+树)


在自定义堆实现的情况下,有没有更好的解决冲突的方法?

最常见的解决hashmap冲突的方法是:

  • deque(PHP是如何实现的)
  • 链表
  • 实际上,只要增加散列值,直到找到一个不是冲突的插槽
  • 对于第一个示例,要使用值“world”存储键“hello”,您可以通过哈希函数获得整数hashmap键(假设C/C++实现):

    然后将该值插入索引
    hash\u key
    处的deque元素:

    hash_map[hash_key].push_back(myvalue);
    
    其中,
    hash_-map
    是您的DEQUE的N索引数组,
    myvalue
    是要插入的对象(请注意,
    myvalue
    应该将自己的
    key
    成员设置为“hello”,以便以后可以检索)

    要在散列映射中找到一个项,可以散列键(“hello”),然后遍历deque直到找到该项。如果哈希函数的摘要空间足够大(例如,一个32位无符号整数=40亿个唯一哈希结果),并且哈希函数给出了一个均匀分布,那么发生冲突的几率足够小(1/2^32),以至于您的数据块可能只有1或2个项(即使您存储了2^33个项),更奇特的结构(AVL树、RB树等等)会使数据结构的速度慢得多

    在发生碰撞之前,存储项目的内存几乎完全耗尽,线性搜索的缓慢成为一个限制因素

    (编辑为添加:您不必[也不应该,对于大型散列函数空间]预分配整个散列映射。也可以使用deque,以便随着散列结果数量的增加而增加。)

    通常的技巧(至少Python和Java都是这样做的)是通过将动态数组或链表放入哈希桶中来解决冲突,如您所建议的。此外,哈希表还获取一个称为最大负载因子的参数,例如2/3。当加载因子高于其允许的最大值(表已满2/3以上)时,a(即,两倍于原始值)将所有数据移动到新的哈希表中


    虽然复制可能很昂贵,但其成本可能超过查找。

    堆在最坏的情况下需要O(n),因为您可能必须遍历整个堆,直到找到所需的元素。堆不提供通用的查找算法。树建议将约束键以某种方式排序,并且排序必须与哈希函数和相等关系一致。如果N=2^32,则需要那么多指针来表示空哈希表。在x86-64上,这是32GB。我的假设是(我没有为它编写代码,因为我很懒),您只在第一次引用deque时创建它们,然后将哈希映射创建为deque本身或int**(数组数组数组),根据需要为哈希指针实例化页面,或者更聪明的方法。我将把这个练习留给真正想要编写它的人。即使N=2^16(x86-64上只有500KB的内存空间),仍然会产生1/65536项的分布,因此每1000000项哈希的深度约为15项/deque。O(M),其中M=15相当小:)
    hash_map[hash_key].push_back(myvalue);