首页 > 代码库 > 跳跃表,整数,压缩列表
跳跃表,整数,压缩列表
跳跃表事一种有序的结构,是有序集合键的底层实现
typedef struct zskiplistNode { // 后退指针 struct zskiplistNode *backward; // 分值 double score; // 成员对象 robj *obj; // 层 struct zskiplistLevel { // 前进指针 struct zskiplistNode *forward; // 跨度 unsigned int span; } level[]; } zskiplistNode;
跳跃表有两种结构定义的,一个是node,一个是list,list控制着node
node就是上面的结构,一个层,每个层有两个元素,一个是前进指针,一个是跨度。还有个后退指针,向后遍历的时候使用,跨度恒为1,还有一个分值和对象。分值就是从小到大依次向后的,doubleleixing类型,节点的对象成员是一个指针,指向一个sds。
list的结构:
head指向头
tail指向尾
lenght记录着跳跃表的长度
level记录着跳跃表内节点层数最高的那层
跨度的概念:
跨度不是用来便利的,是用来计算排位的,rank,通过跨度我们可以知道我们的某一个节点位于跳跃表的第几位
指向null的跨度都是0
整数集合:
typedef struct intset { // 编码方式 uint32_t encoding; // 集合包含的元素数量 uint32_t length; // 保存元素的数组 int8_t contents[]; } intset;
整数集合是无重复的有序的,encoding是编码方式,有16,32,64位的,分别表示不同的范围,length代表的就是长度
因为底层实现是数组,所以有一个内置的数组,这个数组可以自动升级,当加进来的元素位数大于现有的就回自动升级,以最高的位标准,扩大内存,添加移动的时候从后向前进行
自动升级的好处就是
(1)增加灵活性
(2)节省内存,需要的时候扩展,一直秉承着最小对其原值
压缩列表
zlbytes:表示整个压缩列表占用的大小,重分配的时候下需要使用
zltail:计算列表的最后节点距离起始位置的距离,可以分方便的知道尾地址
zllen(2字节):记录节点个数,如果超过65535个的时候,我们需要自己遍历求解
中间都是每一个节点
zlend:0xff表示终止符
中间的entry节点是一个整数或者数组
都包含三个元素
previous_entry_length
前一个节点的长度
可能是一个字节或者是5个字节,如果前一个长度小于254个字节,那就是一个字节存,否则用5个字节,但是5个字节中,第一个字节为0XFE,表示是用5字节存储,后面4个字节表示的是实际长度
encoding:编码方式
可以表示字符或者整数,如果是字符的花,前面分别是00,01,10编码长度分别我1,2,5字节,所表示数组的长度也渐大
如果前面是11,只占一个字节,根据后6位的不同表示的整数的范围也不同
content:存储的数据
连锁更新:
如果每一个元素的大小都在250-253之间,突然增加一个元素,使得第一个+4,造成第二个长度+4,依次类推,这样的话需要进行n次重分配,每次的复杂度位n,那么时间复杂度最坏就是n的2次幂。尽管这样很糟糕,但是发生这种的情况不多,所以我们可以忽略不计
同理,删除一个元素的时候,也有可能造成类似的连锁更新
跳跃表,整数,压缩列表