我正在寻找一个关于哈希表如何工作的解释-用简单的英语为我这样的傻瓜!

例如,我知道它接受键,计算哈希(我正在寻找一个解释),然后执行某种模运算来计算出它在存储值的数组中的位置,但我的知识到此为止。

谁能解释一下过程吗?

编辑:我并不是特别问哈希码是如何计算的,而是对哈希表如何工作的一般概述。


当前回答

这是另一种看待它的方式。

我假设你理解数组A的概念,它支持索引操作,你可以一步找到第I个元素,A[I],不管A有多大。

因此,例如,如果您想存储一组恰好年龄不同的人的信息,一个简单的方法是有一个足够大的数组,并使用每个人的年龄作为数组的索引。这样,你就可以一步获取任何人的信息。

But of course there could be more than one person with the same age, so what you put in the array at each entry is a list of all the people who have that age. So you can get to an individual person's information in one step plus a little bit of search in that list (called a "bucket"). It only slows down if there are so many people that the buckets get big. Then you need a larger array, and some other way to get more identifying information about the person, like the first few letters of their surname, instead of using age.

这是基本思想。不使用年龄,可以使用任何能产生良好价值观传播的人的函数。这就是哈希函数。比如你可以把这个人名字的ASCII表示的每三分之一,按某种顺序打乱。重要的是,您不希望太多人散列到同一个存储桶,因为速度取决于存储桶保持较小。

其他回答

Hashtable inside contains cans in which it stores the key sets. The Hashtable uses the hashcode to decide to which the key pair should plan. The capacity to get the container area from Key's hashcode is known as hash work. In principle, a hash work is a capacity which when given a key, creates an address in the table. A hash work consistently returns a number for an item. Two equivalent items will consistently have a similar number while two inconsistent objects may not generally have various numbers. When we put objects into a hashtable then it is conceivable that various objects may have equal/ same hashcode. This is known as a collision. To determine collision, hashtable utilizes a variety of lists. The sets mapped to a single array index are stored in a list and then the list reference is stored in the index.

到目前为止,所有的答案都很好,并且从不同的方面了解了哈希表的工作方式。这里有一个简单的例子,可能会有帮助。假设我们想要存储一些带有小写字母字符串的项作为键。

正如simon所解释的,哈希函数用于从大空间映射到小空间。对于我们的例子,一个简单的哈希函数实现可以取字符串的第一个字母,并将其映射为一个整数,因此“短吻鳄”的哈希代码为0,“蜜蜂”的哈希代码为1,“斑马”的哈希代码为25,等等。

接下来,我们有一个包含26个存储桶的数组(在Java中可以是数组列表),我们将项放入与键的哈希码匹配的存储桶中。如果我们有不止一个元素键以相同字母开头,它们就会有相同的哈希码,所以它们都会进入存储桶中寻找那个哈希码所以必须在存储桶中进行线性搜索才能找到一个特定的元素。

在我们的例子中,如果我们只有几十个项目,键横跨字母表,它会工作得很好。然而,如果我们有一百万个条目,或者所有的键都以'a'或'b'开头,那么我们的哈希表就不是理想的。为了获得更好的性能,我们需要一个不同的哈希函数和/或更多的桶。

哈希的计算方式通常不取决于哈希表,而是取决于添加到哈希表中的项。在框架/基类库(如。net和Java)中,每个对象都有一个GetHashCode()(或类似)方法,返回该对象的哈希码。理想的哈希码算法和准确的实现取决于对象中表示的数据。

直连地址表

要理解哈希表,直接地址表是我们应该理解的第一个概念。

直接地址表直接使用键作为数组中槽的索引。宇宙键的大小等于数组的大小。在O(1)时间内访问这个键非常快,因为数组支持随机访问操作。

然而,在实现直接地址表之前,有四个注意事项:

要成为有效的数组索引,键应该是整数 键的范围是相当小的,否则,我们将需要一个巨大的数组。 不能将两个不同的键映射到数组中的同一个槽 宇宙键的长度等于数组的长度

事实上,现实生活中并不是很多情况都符合上述要求,所以哈希表就可以救场了

哈希表

哈希表不是直接使用键,而是首先应用数学哈希函数将任意键数据一致地转换为数字,然后使用该哈希结果作为键。

宇宙键的长度可以大于数组的长度,这意味着两个不同的键可以散列到相同的索引(称为散列碰撞)?

实际上,有一些不同的策略来处理它。这里有一个常见的解决方案:我们不将实际值存储在数组中,而是存储一个指向链表的指针,该链表包含散列到该索引的所有键的值。

如果你仍然有兴趣知道如何从头开始实现hashmap,请阅读下面的帖子

其实比这更简单。

哈希表不过是一个包含键/值对的向量数组(通常是稀疏数组)。此数组的最大大小通常小于哈希表中存储的数据类型的可能值集中的项数。

哈希算法用于根据将存储在数组中的项的值生成该数组的索引。

This is where storing vectors of key/value pairs in the array come in. Because the set of values that can be indexes in the array is typically smaller than the number of all possible values that the type can have, it is possible that your hash algorithm is going to generate the same value for two separate keys. A good hash algorithm will prevent this as much as possible (which is why it is relegated to the type usually because it has specific information which a general hash algorithm can't possibly know), but it's impossible to prevent.

因此,您可以使用多个键来生成相同的散列代码。当这种情况发生时,将遍历向量中的项,并在向量中的键和正在查找的键之间进行直接比较。如果找到,则返回与该键关联的值,否则不返回任何值。