《Redis设计与实现》_第五章_跳跃表

介绍

通过在每个节点中维持多个指向其他节点的指针,从而快速访问节点

查找速度:平均O(log N),最坏O(N)

支持顺序性操作

使用跳跃表作为有序集合键的底层实现之一

性质

  1. 每一层都是一个有序的链表,最底层(L1)的链表包含所有元素
  2. 如果一个元素出现在第 n 层的链表中,则它也出现在第 n+1 层
  3. 搜索先从上层搜索,当前面的元素比target大时,则向下一级搜索(即向着更密集的数据找)
  4. 总体来看从左上往右下寻找

实现

IMG_20200818_102630

level:表中层数最大的节点的层数

length:节点数量

跳跃表节点

typedef struct zskiplistNode
{
	struct zskiplistNode * backward;//后退指针
	double score;//分值
	robj * obj;//成员对象
	
	struct zskiplistLevel //层
	{
		struct zskiplistNode * forward; //前进指针
		unsigned int span;//跨度
	}
}

level数组可以包含多个元素,每个元素都包含一个指向其他节点的指针,来加快访问其他节点的速度

感觉幂次规律,随机生成一个[1,32]的值作为level数组的大小,即层的高度

前进指针

每个层都有一个指向表尾方向的前进指针(level[i].forward)

跨度

记录两个节点之间的距离

指向NULL的所有前进指针的跨度都为0

跨度实际是用来计算排位的:在查找某个节点过程中,将沿途访问的所有层的跨度累积起来,得到的结果就是目标节点在跳跃表中的排位(即该节点是第几个节点)

后退指针

可以先通过跳跃表的tail指针访问表尾节点,然后通过后退指针访问倒数第二个节点…,直到遇到指向NULL的后退指针

分值和成员

  1. 分值:跳跃表中所有节点都按分值从小到大排序
  2. 成员对象:指向SDS字符串对象的指针
  3. 跳跃表中成员对象必须唯一,但是分值可以相同
  4. 分值相同的节点按照成员变量的字典序排序

跳跃表

typedef struct zskiplist
{
	struct zskiplistNode * header,*tial;
	unsigned long length;//表中节点的数量
	int level;//表中层数最大的节点的层数
} zskiplist;

使得能O(1)访问表头表尾节点,访问跳跃表长度,获取表中层数最大的节点的层数

t level;//表中层数最大的节点的层数
} zskiplist;


使得能O(1)访问表头表尾节点,访问跳跃表长度,获取表中层数最大的节点的层数

猜你喜欢

转载自blog.csdn.net/weixin_42249196/article/details/108139848