Redis中的链表是一个应用十分广泛的底层数据结构,常用的Redis列表(List)底层实现之一就是链表。我曾用Redis的列表缓存过分布式服务节点的ip。Redis列表的一些操作命令在这里就不做赘述了,有兴趣的同学不妨装个Redis自己动手实践下。
言归正传,继续来讲Redis的底层数据结构——链表。熟悉数据结构的同学一定对链表不会陌生。在src下的adlist.h和adlist.c是如下定义的:
/*
* 双端链表节点
*/
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结构体内保存着链表节点数目的属性len,那么我们在获取链表长度的时候就不需要一直迭代了,时间复杂度只有O(1);并且我们可以在O(1)的时间复杂度内获取到链表的头结点或者尾节点;链表节点用void*指针保存节点值,list内也有三个为节点设置类型的函数,因此链表可以保存各种不同类型的数据。