哈希表 是一种使用 哈希函数 组织数据,以支持快速插入和搜索的数据结构。
有两种不同类型的哈希表:哈希集合和哈希映射。
哈希集合 是 集合 数据结构的实现之一,用于存储 非重复值。哈希映射 是 映射 数据结构的实现之一,用于存储 (key, value) 键值对。在 标准模板库 的帮助下,哈希表是 易于使用的。大多数常见语言(如 Java,C ++ 和 Python)都支持哈希集合和哈希映射。
通过选择合适的哈希函数,哈希表可以在插入和搜索方面实现 出色的性能。
正如我们在介绍中提到的,哈希表 是一种数据结构,它使用哈希函数组织数据,以支持 快速插入和搜索。在本文中,我们将简要说明哈希表的原理。
哈希表的关键思想是使用 哈希函数 将键映射到存储桶。更确切地说,
🌰 示例:

在示例中,我们使用 y = x % 5 作为哈希函数。让我们使用这个例子来完成插入和搜索策略:
插入 和 搜索 是哈希表中的两个基本操作。
在设计哈希表时,你应该注意两个基本因素。
哈希函数是哈希表中最重要的组件,该哈希表用于将键映射到特定的桶。在上一篇文章中的示例中,我们使用 y = x % 5 作为散列函数,其中 x 是键值,y 是分配的桶的索引。
散列函数将取决于 键值的范围 和 桶的数量。
下面是一些哈希函数的示例:

哈希函数的设计是一个开放的问题。其思想是尽可能将键分配到桶中,理想情况下,完美的哈希函数将是键和桶之间的一对一映射。然而,在大多数情况下,哈希函数并不完美,它需要在桶的数量和桶的容量之间进行权衡。
理想情况下,如果我们的哈希函数是完美的一对一映射,我们将不需要处理冲突。不幸的是,在大多数情况下,冲突几乎是不可避免的。例如,在我们之前的哈希函数 y = x % 5 中,1987 和 2 都分配给了桶 2,这是一个冲突。
冲突解决算法应该解决以下几个问题:
根据我们的哈希函数,这些问题与 桶的容量 和可能映射到 同一个桶 的 键的数目 有关。
让我们假设存储最大键数的桶有 N 个键。
通常,如果 N 是常数且很小,我们可以简单地使用一个数组将键存储在同一个桶中。如果 N 是可变的或很大,我们可能需要使用 高度平衡的二叉树 来代替。
哈希集 是集合的实现之一,它是一种存储 不重复值 的数据结构。
哈希映射 是用于存储 (key, value) 键值对的一种实现。
在以前的问题中,键的选择相对简单。不幸的是,有时你必须考虑在使用哈希表时设计合适的键。
解决方案:
实际上,设计关键 是在原始信息和哈希映射使用的实际键之间 建立映射关系。设计键时,需要保证:
- 属于同一组的所有值都将映射到同一组中。
- 需要分成不同组的值不会映射到同一组。
此过程类似于设计哈希函数,但这是一个本质区别。哈希函数满足第一个规则但 可能不满足第二个规则。但是你的映射函数应该满足它们。
在上面的示例中,我们的映射策略可以是:对字符串进行排序并使用排序后的字符串作为键。也就是说,“eat” 和 “ate” 都将映射到 “aet”。
这里有一些为你准备的关于如何设计键的建议。
排序后的字符串 / 数组 作为键。
偏移量 作为键。
TreeNode 作为键。 但在大多数情况下,采用 子树的序列化表述 可能是一个更好的主意。
行索引 或 列索引 作为键。块。
同一对角线 中。