数据结构: 哈希表 | 青训营笔记

127 阅读2分钟

这是我参与「第五届青训营 」笔记创作活动的第16天

哈希表被广泛用于编程中的多种场景: C++中的 unordered_map 是它, Redis中的一个数据结构是它, Java中的 HashMap 是它…… 哈希表这种数据结构已经无孔不入. 会用不如会原理,今天我们就来学一学哈希表的原理,以及我们为什么要用到哈希表.

哈希-总结信息

哈希表的一个重要元素(或者说技术)就是哈希函数. 概括地说,哈希函数是这么一种函数:它接受信息作为输入,然后输出固定大小的信息,作为输入的信息的标识符. 哈希函数尽力保证(但不一定完全保证)每一个输入的信息都会有一个独一无二的标识符. 常见的哈希算法有 MD5 SHA1 等. 这些函数能够输出独一无二的标识符.

哈希表-高级数组

哈希表的查找性能优越.这是因为它建立在巨人的肩膀上-数组. 数组的查找效率非常快,因为只需要按顺序计算元素的位置即可. 试想一下:如果我们将数组的下标替换成哈希,那我们是否能够以数据本身来索引信息? 答案是可以.哈希表就这样诞生了. 在哈希表中,数组的下标被哈希代替. 这样,一个高性能的高级数组就诞生了.

解决冲突-线性探测和链表法

前面说过,哈希函数只是尽力保证哈希值对每个信息都独一无二,但是不完全保证. 当有两个要存入哈希表的信息的哈希完全一样时,就会造成冲突.如何解决这些冲突呢?这里介绍两种简单的方法.

线性探测

当我们发现这个存储空间已经被数据占据了,很自然的一个想法就是换到另外一个地方存储.线性探测的思想就是,当哈希冲突时,依次从哈希冲突的存储空间向下遍历,直到找到一个空白的存储空间,并将冲突的数据存储进去.

链表法

链表法指的是,数组的每个单元不再存储数据,而是存储一个链表.当出现哈希冲突时,将冲突数据存储在这个存储单元的链表中,和原始冲突数据共存.