1,前言
读《Redis设计与实现》所做笔记
作为一种常用的数据结构,链表内置在很多高级的编程语言里面。因为Redis使用的C语言并没有内置这种数据结构,所以Redis构建了自己的链表实现。
2,链表
2.1,链表节点
链表中的每个节点的结构如下所示:
typedef struct listNode{
//前置节点
struct listNode *prev;
//后置节点
struct listNode *next;
//节点的值
void *value;
}listNode
这些节点通过prev
和next
组成双向链表。
多个listNode是可以构建成一条链表,而Redis还用了一个数据结构lsit
来持有这条链表
typedef struct list{
//表头节点
listNode *head;
//表尾节点
listNode *tail;
//链表所包含的节点数量
unsigned long len;
//节点值复制函数
void *(*dup)(void *ptr);
//节点值释放函数
void *(*free)(void *ptr);
//节点值对比函数
int (*match)(void *ptr,void *key);
}list;
- head:表头指针
- tail:表尾指针
- len:链表长度计数器
- dup函数用于复制链表节点所保存的值
- free函数用于释放链表节点所保存的值
- match函数用于对比链表节点所保存的值和另一个输入值是否相等
假设有一个list中有三个listNode,那么这个list会是这样的:
2.2,特性
基于Redis链表的这种实现方式,其有以下的特性:
- 双端:链表节点带有prev和next指针,获取某个节点的前置节点和后置节点的复杂度都是O(1)
- 无环:表头节点的prev和表尾节点的next指针都指向NULL,对链表的访问以NULL为终点
- 带表头指针和表尾指针:通过list结构的head指针和tail指针,程序获取链表的表头节点和表尾节点的复杂度为O(1)
- 带链表长度计数器:因为有len属性记录list链表节点的数量,程序获取链表节点数量的复杂度为O(1)
- 多态:链表节点使用void *指针来保存节点值,并且可以通过list结构的dup、free、match三个属性为节点值设置类型特定函数,并且链表可以用于保存各种不同类型的值。