redis基础数据结构(五) 跳跃表

跳跃表是一种对顺序链表的改进,将查找顺序链表的O(N)时间优化为O(logN)时间,空间增加约两倍,有两种常见变体,一种是随机跳跃表,使用随机算法决定每个节点的高度,缺陷有产生随机数的开销;另一种是123确定性跳跃表,除了头和尾,第n层相邻的两个节点之间只有1个,2个或者3个第n-1层的节点,当插入或删除时调整结构;另一种对顺序链表的O(logN)优化是,使用一个指针数组,数组中每个指针指向一个链表节点,从而变成二分查找,得到一个O(logN)的时间界,这种方法需要的空间少,缺陷是在链表增删节点时需要对指针数组进行大量的内存搬移,底层调用C库函数memmove可以防止重叠内存拷贝造成踩内存,但是性能堪忧。

redis的跳跃表使用的是随机跳跃表,代码在server.h和t_zset.c中,server.h提供了跳跃表节点和头的定义,如下

typedef struct zskiplistNode {
    sds ele;
    double score;
    struct zskiplistNode *backward;
    struct zskiplistLevel {
        struct zskiplistNode *forward;
        unsigned int span;
    } level[];
} zskiplistNode;

typedef struct zskiplist {
    struct zskiplistNode *header, *tail;
    unsigned long length;
    int level;
} zskiplist;

zskiplistNode是跳跃表节点,包括一个可变长字符串,一个后向指针,level结构中每一层都有一个前向指针,以及一个scan表示跨过几个level[0]元素可以达到本层下一个节点。zskiplist是头,包括头尾指针,长度和层数

t_zsets中提供的api:

zslCreateNode:创建一个跳跃表节点

zslCreate:创建一个跳跃表头

zslFreeNode:释放一个节点,包括其中的sds

zslFree:删除整个跳跃表,包含头和level[0]的每个节点的内存

zslRandomLevel:返回一个随机层数,使用幂律相似分布,每层个数约是上一层的1/4

zslInsert:插入一个节点到zsl中

zslDeleteNode:删除一个节点,但是不释放节点内存,外层提供每层删除位置

zslDelete:删除一个节点,根据外层需要判断是否需要删除节点内存

zslValueGteMin:返回value和spec中的最小值的大小关系,有flag控制是大于还是大于等于

zslValueLteMax:返回value和spec中的最大值的大小关系,有flag控制是小于还是小于等于

zslIsInRange:判断提供的range中的范围是否是rsl范围的子集

zslFirstInRange:返回给定range中的第一个元素

zslLastInRange:返回给定range中的最后一个元素

zslDeleteRangeByScore:根据score删除给定range中的元素,同时删除dict中的ele

zslDeleteRangeByLex:根据ele删除给定range中的元素,同时删除dict中的ele

zslDeleteRangeByRank:根据提供的level[0]的索引范围,删除这个范围内的节点

zslGetRank:查找给定rank和ele的节点在level[0]中的索引

zslGetElementByRank:查找并返回level[0]中索引是给定rank值的节点

zslParseRange:解析range范围段,从用户态参数中解析数据时调用此函数

zslParseLexRangeItem:给range的一端赋值,并给可变长字符串分配内存

zslFreeLexRange:释放range中的可变长字符串,包括min和max两个

zslParseLexRange:根据提供的min和max解析范围段可变长字符串

sdscmplex:是sdscmp的包装,比较两个可变长字符串的大小

zslLexValueGteMin:判断给定的value是否大于或大于等于min

zslLexValueLteMax:判断给定的value是否小于或小于等于max

zslIsInLexRange:判断给定range是否是zsl范围的子集

zslFirstInLexRange:根据zsl的ele查找给定range中的第一个节点

zslLastInLexRange:根据zsl的ele查找给定range中的最后一个节点


猜你喜欢

转载自blog.csdn.net/kdb_viewer/article/details/80744229