数据结构与算法学习笔记(八)——散列表(二)

本文介绍了散列表结合双向链表的数据结构,用于解决散列冲突和提高LRU缓存算法的性能。在LRU中,查找、删除和插入操作均能在O(1)时间内完成。哈希算法被广泛应用于安全加密、唯一标识、数据校验等场景,并在负载均衡、数据分片和分布式存储中起到关键作用。当服务器数量变化时,一致性哈希算法能有效解决服务器编号的重新计算问题。
摘要由CSDN通过智能技术生成

散列表+双向链表

在这里插入图片描述
1、上一篇讲到使用链表法来解决散列冲突,是单链表。这一节为散列表+双向链表的使用。但该双向链表与散列表无任何关系,与链表法中的单链表不一样,散列表+双向链表只是将两种数据结构结合在一起,用于更高效的查询、插入和删除。

2、图中可以看出,双向链表中有四个指针,data存储数据,prev、next分别为前驱和后继指针,将结点串在双向链表中,保证双向链表的有序性,提高插入和删除的性能。
hnext表示将结点串在散列表的拉链中,作用类似于链表法中的单链表的 next指针,即用于解决散列冲突
即,prev和next表示串联的是整个双向链表(纵向),hnext串联的是散列表中的该条拉链表(横向)。

3、应用——LRU
<1>LRU算法:最近最长时间未使用缓存淘汰算法。使用散列表+双向链表的数据结构实现LRU算法,对缓存数据的操作主要为查找、删除、插入。
<2>查找:先计算散列值,在散列表中进行查找,此时间复杂度为O(1)。然后将该数据移动到双向链表的尾部,注意此操作不会改变节点在双向链表中的位置,只改变next指针的指向,将原本的尾结点的next指针指向该节点,再将该节点的next指针指向Null即可。
<3>删除:通过散列表找到要删除的节点后,在双向链表中删除该节点。因双向链表可以直接获取前驱指针,因此删除的时间复杂度也为O(1)
<4>插入:若插入的数据已在缓存中则移动到双向链表尾部。若不在且空间未满时,直接插入到双向链表尾部;若不在且空间已满时,则删除头结点,插入双向链表尾部。
<5>JAVA中的LinkedHashMap的实现原理同LRU
<6>Redis的有序集合则使用了散列表+跳表

哈希算法

1、哈希算法:将任意长度的二进制串映射为固定长度的二进制值串,产生的哈希值长度是固定且有限的。有限是因为表示二进制的位数是有限的,根据鸽巢原理(10个巢,11个鸽子,必定有一个巢内有大于一只鸽子),必然会有哈希值下相同的情况。当然哈希算法产生的哈希值越长,散列冲突的概率也越低,但是计算时间也很长。
2、哈希算法的应用:
(1)安全加密算法:MD5、SHA
(2)唯一标识:对大数据进行信息摘要
(3)数据校验
(4)散列函数
(5)负载均衡
(6)数据分片
(7)分布式存储
其中5、6、7的原理是将key值进行哈希,将哈希值与服务器个数进行取模,得到的值即为存储该key的服务器编号
则有问题:若服务器不够,则要进行服务器扩容,之前计算的服务器编号则要全部重新计算。因此一致性哈希算法可以解决此问题(建议单独百度该算法,不做详解)

图源:王争——数据结构与算法之美

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值