HashTable 哈希/散列表 面试基础

HashTable 哈希/散列表

1. 基本思想

哈希表也叫散列表,用于存储key-value键值对,通过将key映射到表中的一个位置来以常数的时间实现插入、删除和查找的技术。

使用哈希/散列函数将要查找的键值转化为数组的索引,在理想状态下,不同的键对应不同的索引,如果每个键对应的索引都不同的话,其实就是直接用数组存储。但如果key的范围很大的话,需要的数组太大(比如处理海量数据时的bitHash),内存消耗上不划算。一般来说,为了折中,用小于键范围的数组(容量为TableSize)来存储。此时,不同的键就会对应相同的索引,这个时候,需要解决哈希冲突的问题。

2. 哈希函数

对于整数来说,最简单的哈希函数就是 key mod TableSize,这个时候,保证table的大小为素数时,该哈希函数能够对随机整数实现平均分配。

下面是一些在应用领域较为出名的哈希算法:

  • MD5,信息摘要算法5,确保信息传输完整一致。MD5是输入不定长度信息,输出固定长度128bits的算法。
  • SHA-1,用于HTTPS传输和软件签名。
  • SHA-2:SHA-224/SHA-256/SHA-384/SHA-512并成为SHA-2
  • SHA-3:之前命名为Keccak算法,是一个加密杂凑算法。

3. 解决哈希冲突的方法

3.1 分离链接法(拉链法)

拉链法可用于避免哈希冲突,它的思想是把hash相同的元素存放在链表中,将数组和链表结合起来,平衡时间和空间,实现快速的查找插入和删除。

即,将数组中的每个元素指向一个链表,链表中的每一个节点都存储索引相同的键值对。拉链法的数组长度要足够大,使得链表尽量小,以保证查找效率。

在这里插入图片描述

可以指定散列表的最大装载因子 load factor,一旦超过就会rehashing。

load factor = 散列表中的元素个数与散列数组大小的比值。

一般设定为1,即所有存储的元素个数大于数组大小时,就rehashing。

3.2 线性探测法

与拉链法不同的是,该方法在检测到哈希冲突时,不拉出一个链表进行存储,而是逐个探测找出后序的空单元来解决冲突,如下图所示,插入Sandra dee时,因为152已被John smith占据,故放置于153,同理,插入Ted Baker时,虽然hash值为153,但因为被占据,就顺序放到154。

在这里插入图片描述
在线性探测法中,如果hash函数不均衡,很容易出现聚集的区块,为了保证效率,装填因子一般设为0.5,此时插入平均需要2.5次探测,成功查找平均需要1.5次探测。

3.3 平方探测法

为了解决线性探测法中一次聚集问题的冲突解决办法。平方探测就是先探测后序的第1个,如果被占用,则探测后序的第 2 2 = 4 2^2=4 22=4个,如果还被占用,探测后序的第9个。

装填因子一般低于0.5,即确保散列表大小至少是表中元素的两倍大,这样平方探测解法总可以实现。

3.4 双散列

最后一个解决冲突的办法是双散列,在计算探测位置时应用第二个哈希函数。当键为字符串时,由于散列函数的计算比较耗时,通常使用简单易行的平方探测法。

4. 扩充再散列rehash

如果散列表中的元素太多,超过设置的装填因子,那么操作的运行时间开始过长,此时进行rehash,建立一个新表(一般是原表大小两倍后的第一个素数),使用新的哈希函数扫描原表,将元素复制到新表里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值