redis中通过zskiplist 来表示一个跳跃表
typedef struct zskiplist {
// 跳跃表的表头和表尾
struct zskiplistNode *header, *tail;
// 表示有跳跃表中有几个节点
unsigned long length;
// 跳跃表最大的层数
int level;
} zskiplist;
//跳跃表的单个节点的数据结构如下所示:
typedef struct zskiplistNode {
// 具体结构在后面
robj *obj;
// 节点的分值
double score;
struct zskiplistNode *backward;
struct zskiplistLevel {
// 前向指针
struct zskiplistNode *forward;
// 跨度
unsigned int span;
} level[];
} zskiplistNode;
#robj 结构体采用了c语言中的位域,为了节省内存
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:REDIS_LRU_BITS; /* lru time (relative to server.lruclock) */
int refcount;
void *ptr;
} robj;
从跳跃表的数据结构可以看出跳跃表是几个跳跃节点组成的list,组成跳跃表的节点之前根据里跳跃表的远近采取分层的方式,也就是所谓的level
本质上说跳跃表也是一种链表,其操作也就是链表的那几种常用操作。
zslCreate 用于新建一个新的跳跃表
zskiplist *zslCreate(void) {
int j;
zskiplist *zsl;
// 分配空间
zsl = zmalloc(sizeof(*zsl));
// 初始化levl和length
zsl->level = 1;
zsl->length = 0;
// 申请表头节点
zsl->header = zslCreateNode(ZSKIPLIST_MAXLEVEL,0,NULL);
for (j = 0; j < ZSKIPLIST_MAXLEVEL; j++) {
#表头节点赋值,这里ZSKIPLIST_MAXLEVEL 等于32 ,可见跳跃表最多有32个子表.这里一次性创建了32 个子表,然后分别最着32个子表初始化
zsl->header->level[j].forward = NULL;
zsl->header->level[j].span = 0;
}
zsl->header->backward = NULL;
// 表尾赋值为null
zsl->tail = NULL;
return zsl;
}
zskiplistNode *zslCreateNode(int level, double score, robj *obj) {
// 根据level 分配空间,可见跳跃表在创建的时候就已经申请了可以支持的最大内存空间
zskiplistNode *zn = zmalloc(sizeof(*zn)+level*sizeof(struct zskiplistLevel));
// 这里的obj 为null,score 为0
zn->score = score;
zn->obj = obj;
return zn;
}
redis中的zskiplist
最新推荐文章于 2024-08-16 23:59:24 发布