C 语言本身没有链表,Redis 自己设计了一个链表数据结构
双向链表结构设计
链表节点结构设计:
// 链表节点
typedef struct listNode {
struct listNode *prev; // 前置节点
struct listNode *next; // 后置节点
void *value; // 节点的值
} listNode;
链表结构设计:
// 链表
typedef struct list {
listNode *head; // 链表头节点
listNode *tail; // 链表尾节点
void *(*dup)(void *ptr); // 节点值复制函数
void (*free)(void *ptr); // 节点值释放函数
int (*match)(void *ptr, void *key); // 节点值比较函数
unsigned long len; // 链表节点数量
} list;
list
结构为链表提供了链表头指针 head
、链表尾节点 tail
、链表节点数量 len
、以及可以自定义实现的 dup
、free
、match
函数
链表的优势与缺陷
优势:
- 不必开辟连续大空间
- 获取某个节点的前置节点或后置节点时间复杂度只需 O(1)
- 因为
listNode
的结构有prev
和next
指针 - 这两个指针都可以指向
NULL
,所以链表是无环链表
- 因为
- 获取链表的表头节点和表尾节点的时间复杂度只需 O(1)
- 因为
list
结构有表头指针head
和表尾节点tail
- 因为
- 获取链表中的节点数量的时间复杂度只需 O(1)
- 因为
list
结构有链表节点数量len
- 因为
- 链表节点可以保存各种不同类型的值
- 因为
listNode
使用void*
指针保存节点值 - 并且可以通过
list
结构的dup
、free
、match
函数指针为节点设置该节点类型特定的函数
- 因为
缺陷:
- 链表每个节点之间的内存是不连续的,意味着无法很好利用 CPU 缓存加速访问
- 每保存一个值都需要一个链表节点结构的内存分配,需要频繁分配内存且内存开销较大