Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/EmptyTag/144.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 实现哈希表_C++_Algorithm_Hash_Hashmap_Hashtable - Fatal编程技术网

C++ 实现哈希表

C++ 实现哈希表,c++,algorithm,hash,hashmap,hashtable,C++,Algorithm,Hash,Hashmap,Hashtable,几天前,我开始阅读关于实现各种数据结构的书籍,开始研究散列表,并在某个特定点上陷入困境 我对哈希表如何实现的理解: 密钥K被传递给散列函数H,散列函数H返回K,HK的散列版本。HK应该至少是一个uint32_t来解释冲突,我们有一个大小为X的数组,该项存储在该数组的索引HK处。。但是,这难道不需要一个至少长度为uint32_t的预分配数组(或者不管H的返回值是什么)吗?假设我们不将数据本身存储在该数组中,而是将ptr存储到数据中,那么我们需要一个长度为uint32的ptr\t数组。。这似乎相当浪

几天前,我开始阅读关于实现各种数据结构的书籍,开始研究散列表,并在某个特定点上陷入困境

我对哈希表如何实现的理解: 密钥K被传递给散列函数H,散列函数H返回K,HK的散列版本。HK应该至少是一个uint32_t来解释冲突,我们有一个大小为X的数组,该项存储在该数组的索引HK处。。但是,这难道不需要一个至少长度为uint32_t的预分配数组(或者不管H的返回值是什么)吗?假设我们不将数据本身存储在该数组中,而是将ptr存储到数据中,那么我们需要一个长度为uint32的ptr\t数组。。这似乎相当浪费,64位意味着内存使用: 2^32*8=34359738368字节或~32GB仅用于数据的PTR数组,这显然不是它在现实生活中实际实现的方式


那么我遗漏了什么呢?

您应该构建您的哈希表,以便对其进行扩展。有一些方法可以做到这一点。读一下会有帮助的。在本例中,使用了链表。如果不再有空值,还需要扩展表。您将遇到以下问题:如果扩展map,则H函数可以为旧K键返回新的HK值。所以你必须思考如何解决这个问题。其中一种方法是在扩展表时重新加载所有值。如果不经常扩展它,这是正常的。

这取决于实现。这有三种基本方法:

1) 使用小散列。因此,不用32位哈希,比如说,使用8位哈希

2) 使用了多级散列。因此,例如,12位散列可以确定条目进入哪个“bucket”,但只有当完整的32位散列匹配时才会发生冲突。每个存储桶都存储在链表或类似结构中。(可能是为搜索其中的完整32位散列而优化的。)


3) 使用稀疏数组。这些数据结构实际上不需要为未填充的插槽存储空格。(实际上,它可能是完全不同的东西,比如一棵树,但它就像一个具有高效搜索功能的稀疏数组。)

实际上,您有一个由一些更小、固定数量的bucket组成的数组,这些bucket或者使用链接(结果是一个链表)或者探测(最糟糕的例子是:如果使用哈希(x),则在冲突时尝试哈希(x)+1)。你可以根据桶的大小选择uint32和mod,这是最简单的情况

您可以定义一个负载因子—一旦阵列的N%已满,我们将(比方说)将阵列的大小增加一倍,并将所有内容重新灰化到新阵列中。比方说,使用率在50%到75%之间


嗯,你说那不是很贵吗?嗯,不是真的。假设每次将数组的大小增加一倍。因此,添加N个项目,最后一个项目触发一个副本。N在O(1)处添加,然后添加一个O(N)副本。但是wait-O(N)/N的平均值为O(1),因此,假设您明智地选择了负载因子,那么添加的摊销平均成本仍然是O(1)。

哈希表的典型实现是一个链表数组。链表可以很容易地替换为另一个数据结构,因此从现在起我们将其称为
Bucket

想法很简单:

class HashTable {
public:


private:
  std::vector<Bucket*> _array;
};
类哈希表{
公众:
私人:
std::vector_数组;
};

然后,取HK并将其缩小到数组中,通常使用一个模:
HK%大小(\u数组)
,它给出要使用的bucket的索引。

我认为典型的实现不是使用数组而是使用链表。我认为典型的实现不是使用链表而是使用数组。关于冲突,当使用哈希表时,会出现冲突。它们应该得到处理,而不是避免。可以通过适当的散列和维度来最小化它们。@bamboon:实际上,您使用一个链表数组来实现日常操作。在发生冲突的情况下,它并不理想,而且(项目之间)引用的局部性很差,但操作的复杂性是可以预测的。@MatthieuM。是的,这是一个误会,我以为他说的是第二阶段。如果重新哈希,当它是一个哈希集时会发生什么,也就是说,你没有原始数据可以重新哈希?@KimSun wu:你可以简单地将哈希存储在数据旁边,以避免重新计算。@MatthieuM。即使在不扩展表的情况下,存储完整的32位散列也是访问的有效优化;在检查相等性之前比较32位哈希值。@JamesKanze:对!我甚至没有想过这一点(但是,我自己从来没有真正实现过哈希表…)哈希表或哈希映射是一种数据结构,它使用哈希函数将标识值(称为键)映射到它们的关联值。哈希表中有键和哈希值。您只需要计算旧键的新值。如果你没有键(即只有一组散列值),为什么你需要它呢?我刚才说的是散列集,但是Matthieu M回答了这个问题。