数据结构-散列表(hash table)

6.1 散列表的概念

散列表又叫哈希(hash)表,是根据键(key)直接访问在内存存储位置的值(value)的数据结构,由数组演化而来(根据数组支持按照下标进行随机访问数据的特性)。

eg:有一组数据2023ZHBJ001、2023ZHBJ002、...、2023ZHBJ100。其中2023代表年份,zh代表中国,bj代表北京,001代表选手编号,此时这一串数据就代表一个选手

那么此时,我们如何将这一串数据转换为key存进数组作为数组下标呢?此时我们介绍下面这个方法散列函数。

6.2 散列函数

概念:将key映射为数组下标的函数就叫散列函数。可以表示成hashvalue=hash(key)。

散列函数的要求:

1.散列函数计算得到的key值必须是大于等于0的正整数,因为hashvalue要作为数组下标。

2.如果key1==key2,那么经过hash后得到的hash值也必须相等:hash(key1)==hash(key2)。

3.如果key1 != key2,那么经过hash后得到的hash值也必须不相等:hash(key1)!=hash(key2)。

注:第三点不太好实现,因为实际情况下想找一个散列函数能够做到对于不同key计算得到的散列值不相同是几乎不可能的,这就是散列冲突。

6.3 散列冲突(哈希碰撞、哈希冲突)

概念:多个key值映射到同一个数组下标,这就是散列冲突。

那么如何解决这个呢,就要介绍到下面的拉链法。

6.4 拉链法

在散列表中,数组每个下标的位置我们称之为桶(bucket)或者槽(slot),每个桶(槽)都对应一个链表,所有的散列值相同的元素都存进相同槽位对应的链表中。这样就做到了让多个hash值相同的元素存到同一个索引下,这就解决了hash冲突

6.5 拉链法时间复杂度

6.5.1 插入

通过散列函数计算出对应散列槽位,将其插入进对应散列槽位即可,时间复杂度是O(1);

插入流程:根据key经过hash计算得到数组索引,然后将数据挂到索引上,这样不需要遍历,只需要计算就可完成,效率比较高,所以时间复杂度是O(1)。

6.5.2 删除、查找

当查找、删除时,同样是先通过hash计算得到数组索引,然后遍历对应槽位的链表进行查找删除。

6.5.2.1 一般情况下

基于链表法解决冲突时查询的时间复杂度时O(1)。因为链表中数据并不多

6.5.2.2 特殊情况下

当数据量够多,产生了大量的hash冲突,就会将数据挂到同一索引下,导致某一个槽位的链表很长,那么此时散列表就退化成了链表,当再去这个索引下查找元素时,就要遍历链表,所以时间复杂度为O(n)。

6.5.2.3 第三种情况下

当链表过长时,将链表法中的链表改造为其他高效的数据结构,比如红黑树,这样遍历时时间复杂度为O(logn)。

注:将链表改为红黑树的一个重要原因也是为了防止DDos攻击(分布式拒绝服务攻击)。

可以理解为,有人恶意伪造key,造成大量hash冲突,就会在数组索引中产生大量链表,就会导致访问散列表的效率很低。

  • 18
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值