数据结构中的哈希2025年6月17日 | 阅读 13 分钟 哈希是计算机科学中一种流行的技术,它涉及将大型数据集映射到固定长度的值。它是一个将可变大小的数据集转换为固定大小数据集的过程。高效执行查找操作的能力使得哈希成为数据结构中的一个基本概念。 什么是哈希?哈希算法用于将输入(如字符串或整数)转换为固定大小的输出(称为哈希码或哈希值)。然后使用此哈希值作为数组或哈希表中的索引来存储和检索数据。哈希函数必须是确定性的,这意味着对于给定的输入,它总是产生相同的结果。 哈希通常用于为数据创建一个唯一标识符,该标识符可用于在大型数据集中快速查找该数据。例如,Web 浏览器可以使用哈希来安全地存储网站密码。当用户输入其密码时,浏览器会将其转换为哈希值,并将其与存储的哈希值进行比较以验证用户。 什么是哈希键?在哈希的上下文中,哈希键(也称为哈希值或哈希码)是由哈希算法生成的固定大小的数值或字母数字表示。它通过一个称为哈希的过程从输入数据(如文本字符串或文件)派生而来。 哈希涉及对输入数据应用特定的数学函数,该函数会生成一个唯一的哈希键,该键通常是固定长度的,无论输入大小如何。生成的哈希键本质上是原始数据的数字指纹。 哈希键具有多种用途。它通常用于数据完整性检查,因为即使输入数据发生微小变化,也会产生截然不同的哈希键。哈希键还用于在哈希表或数据结构中进行高效的数据检索和存储,因为它们允许快速查找和比较操作。 哈希如何工作?哈希过程可分为三个步骤:
哈希算法有许多哈希算法,每种算法都有其独特的优点和缺点。最流行的算法包括以下几种:
![]() 哈希函数哈希函数:哈希函数是一种数学运算,它接受输入(或键)并输出一个称为哈希码或哈希值的固定大小的结果。为了保证确定性,哈希函数必须始终为相同的输入产生相同的哈希码。此外,哈希函数应为每个输入生成一个唯一的哈希码,这被称为哈希属性。 有不同类型的哈希函数,包括:
此方法涉及将键除以表的大小,并取余数作为哈希值。例如,如果表的大小为 10,键为 23,则哈希值为 3 (23 % 10 = 3)。
此方法涉及将键乘以一个常数,并取乘积的小数部分作为哈希值。例如,如果键为 23,常数为 0.618,则哈希值为 2 (floor(10*(0.61823 - floor(0.61823))) = floor(2.236) = 2)。
此方法涉及使用一组哈希函数中的一个随机哈希函数。这确保了哈希函数不会偏向任何特定的输入,并且可以抵抗攻击。 冲突解决哈希中的主要挑战之一是处理冲突,当两个或多个输入值产生相同的哈希值时会发生冲突。有各种技术用于解决冲突,包括:
冲突解决示例让我们继续以大小为 5 的哈希表为例。我们想在哈希表中存储键值对“John: 123456”和“Mary: 987654”。这两个键都产生相同的哈希码 4,因此会发生冲突。 我们可以使用链表法来解决冲突。我们在索引 4 处创建一个链表,并将键值对添加到列表中。此时的哈希表如下所示: 0: 1: 2: 3: 4: John: 123456 -> Mary: 987654 5: 哈希表哈希表是一种在数组中存储数据的数据结构。通常,会选择一个比可以放入哈希表中的元素数量更大的数组大小。使用哈希函数将键映射到数组中的一个索引。 当要在哈希表中添加新元素时,哈希函数用于定位需要插入元素的索引。如果没有发生冲突,该元素将被添加到该索引。如果发生冲突,则使用冲突解决方法在数组中查找下一个可用槽。 为了从哈希表中检索元素,哈希函数用于定位存储该元素的索引。如果未在该索引处找到元素,则使用冲突解决方法在链表中(如果使用链表法)或在下一个可用槽中(如果使用开放寻址法)搜索该元素。 哈希表操作可以对哈希表执行几种操作,包括:
创建哈希表哈希经常用于构建哈希表,哈希表是一种数据结构,可以快速地进行数据插入、删除和检索。构成哈希表的桶数组中的每个数组可以存储一个或多个键值对。 要创建哈希表,我们首先需要定义一个哈希函数,该函数将每个键映射到数组中的一个唯一索引。一个简单的哈希函数可能是将键中字符的 ASCII 值相加,然后除以数组大小取余数。但是,此哈希函数效率低下,可能导致冲突(两个键映射到同一索引)。 为了避免冲突,我们可以使用更高级的哈希函数,它们可以在数组中更均匀地分布哈希值。一种流行的算法是 djb2 哈希函数,它使用按位运算来生成哈希值。 此哈希函数以字符串作为输入,并返回一个无符号长整数哈希值。该函数初始化哈希值为 5381,然后遍历字符串中的每个字符,使用按位运算生成新的哈希值。最后返回哈希值。 C++ 中的哈希表在 C++ 中,标准库提供了一个名为 unordered_map 的哈希表容器类。unordered_map 容器使用哈希表实现,并提供对键值对的快速访问。unordered_map 容器使用哈希函数来计算键的哈希码,然后使用开放寻址法来解决冲突。 要在 C++ 中使用 unordered_map 容器,您需要包含 说明
程序输出 ![]() 将数据插入哈希表要将键值对插入哈希表,我们首先需要为数组编制索引以存储键值对。如果另一个键映射到同一索引,则会发生冲突,我们需要适当地处理它。一种常见的方法是使用链表法,其中数组中的每个存储桶都包含一个键值对的链表,这些键值对具有相同的哈希值。 以下是如何使用链表法将键值对插入哈希表的示例: 说明
但是,如果 hash_table 数组中该索引处已经存在一个节点,则函数需要处理冲突。它遍历从当前节点 (hash_table[hash_value]) 开始的链表,并移动到下一个节点,直到到达末尾 (curr_node->next != NULL)。一旦到达列表末尾,新节点就会作为下一个节点附加 (curr_node->next = new_node)。 C++ 中哈希的实现让我们看看在 C++ 中使用开放寻址法和线性探测法进行冲突解决的哈希实现。我们将实现一个存储整数的哈希表。 说明
程序输出 ![]() 哈希的应用哈希在计算机科学中有许多应用,包括:
哈希的优点
哈希的局限性
结论总而言之,哈希是数据结构中一种广泛使用的技术,它提供了对数据的有效访问。它涉及使用哈希函数将大量数据映射到较小的哈希表,这减少了搜索特定数据元素所需的时间。哈希函数确保数据存储在哈希表中的唯一位置,并允许在需要时轻松检索数据。 与链表和数组等其他数据结构技术相比,哈希具有一些优点,例如更快的检索时间、高效的内存利用率以及由于使用了良好的哈希函数而减少的冲突。但是,它也有一些局限性,包括可能发生哈希冲突,以及需要一个能够将数据均匀分布到哈希表中的良好哈希函数。 总的来说,哈希是一项强大的技术,广泛应用于数据库索引、拼写检查和密码存储等许多应用程序中。通过使用良好的哈希函数并实现适当的冲突解决技术,开发人员可以优化其应用程序的性能,并为用户提供无缝的体验。 下一主题数据结构中的哈希函数 |
我们请求您订阅我们的新闻通讯以获取最新更新。