Redis-有序集合(Zset)数据结构

集合概念

Set

Set类似于Java中的HashSet 。Redis中的set类型是一种无序集合,集合中的元
素没有先后顺序,并且不可重复。

当需要存储一个列表数据,又不不能出现重复数据时,Set 是一个很好的选择,并且set提供了判断某个成员是否在一个Set集合内的接口,List是没有这种接口的

可以基于set轻易实现交集、并集、差集的操作。Redis 可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程。

Zset

和Set相比,sorted set增加了一个权重参数score, 使得集合中的元素能够按score
进行有序排列,还可以通过score的范围来获取元素的列表。有点像是Java中HashMap和TreeSet的结合体。

其有两种实现方式,分别是ziplist和skiplist

实现方式

当有序集合保存的元素数量小于128个或者有序集合保存的所有元素的长度小于64字节时,Zset选用ziplist实现,其他情况选用skiplist实现;

ziplist - 压缩列表

ziplist,顾名思义压缩列表,每个集合元素使用两个紧挨在一起的压缩列表节点来保存,第一个节点保存元素的value,第二个元素保存元素的score;
在这里插入图片描述

skiplist - 跳表

跳表(skip List)是一种随机化的数据结构,基于并联的链表,实现简单,插入、删除、查找的复杂度均为logn。

简单说来跳表也是链表的一种,只不过它在链表的基础上增加了跳跃功能,正是这个跳跃的功能,使得在查找元素时,跳表能够提供logn的时间复杂度

普通链表
在这里插入图片描述

在普通链表中,如果我们要查找某个元素,那么需要从头开始逐个进行比较,直到找到包含数据的那个节点,或者找完所有的节点(没找到)。

  • 这样的话,时间复杂度为O(n);
  • 当我们要插入新数据的时候,也要经历同样的查找过程,从而确定插入位置

跳表

在这里插入图片描述

假如我们每相邻两个节点增加一个指针,让指针指向下下个节点,如上图,比如节点是1 - 2 - 3 - 4 - 5,增加节点1 - 3 - 5

这样形成一个新的链表,但它包含的节点个数只有原来的一半1,3,5

  • 当我们想查找数据的时候,可以先沿着这个新链表进行查找。当碰到比待查数据大的节点时,再回到原来的链表中进行查找。
  • 比如查找3,之间可用从1指向3,即可跳过2,当数据量大的时候,只需要查询原有数据量的一半

利用同样的方式,我们可以在上层新产生的链表上,继续为每相邻的两个节点增加一个指针,从而产生第三层链表。
在这里插入图片描述
依次类推,当链表足够长的时候,这种多层链表的查找方式能让我们跳过很多下层节点,大大加快查找的速度。

skiplist正是受这种多层链表的想法的启发而设计出来的。实际上,按照上面生成链表的方式,上面每一层链表的节点个数,是下面一层的节点个数的一半,这样查找过程就非常类似于一个二分查找,使得查找的时间复杂度可以降低到O(log n)。

存在问题

这种数据结构可用加快查询速度,但是在插入删除数据是就会出现问题

  • 新插入一个节点之后,就会打乱上下相邻两层链表上节点个数严格的2:1的对应关系。
  • 如果要维持这种对应关系,就必须把新插入的节点后面的所有节点(也包括新插入的节点)重新进行调整,这会让时间复杂度重新蜕化成O(n)。
  • 删除数据也有同样的问题。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值