跳跃表(Skip List)是一种基于链表的数据结构,它可以实现诸如有序集合(Sorted Set)等数据结构,能够提供平均 O(log n) 的查找效率。Redis中就使用跳跃表来实现有序集合。
1. 跳跃表简介
在一般的链表中,如果我们需要查询一个元素,可能需要遍历链表,这样的时间复杂度是O(n)。而跳跃表通过维护一个多层的链表,为链表查询提供了“快速通道”。
在跳跃表中,每一个节点包含多个“层”,每一层都有一个前进指针指向下一个节点,通过这种方式,跳跃表能够在横向和纵向上进行查询,大大提高了查询效率。
2. Redis中的跳跃表实现
在Redis中,跳跃表由zskiplist
和zskiplistNode
两种结构构成:
typedef struct zskiplistNode {
robj *obj;
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;
其中,zskiplist
保存了跳跃表的信息,包括头节点、尾节点以及长度等信息,而zskiplistNode
则用于表示跳跃表的节点。
每个跳跃表节点包含以下信息:
- 层(level):每个节点包含多个层,每一层都包含一个前进指针(forward)和一个跨度(span)。
- 前进指针(forward):指向同一层中的下一个节点。通过前进指针,跳跃表可以在同一层中快速地定位目标节点。
- 跨度(span):记录前进指针所跨越的节点个数。跨度的作用是在跳跃表中快速定位目标节点。
- 后退指针(backward):指向同一层中的前一个节点。通过后退指针,跳跃表可以在同一层中快速地定位前一个节点。
在Redis的有序集合中,跳跃表起到了至关重要的作用。通过高效的查找、插入和删除操作,为Redis提供了强大的性能支持。
3. 跳跃表的查询、插入与删除
跳跃表的查询、插入和删除操作都能够在O(log n)的时间复杂度内完成,这是因为跳跃表中的每一个节点都包含了多个层,这些层通过前进指针和后退指针,实现了在不同层之间的快速跳转。