链表优点
1.链表提供高效的节点重排能力
2.顺序访问节点方式
3.通过增删节点来调整链表长度
Redis实现链表
Redis构建了自己的链表实现。
在Redis中的应用
示例:列表键的底层实现之一就是链表。
列表键包含数量较多元素时,或者包含的元素都是比较长的字符串时,Redis会用链表来作为列表键的底层实现。
如integers列表键包含了1-1024共1024个整数。
此列表键的底层实现就是一个链表。
链表中每个节点保存一个整数值。
链表和链表节点的实现
每个链表节点使用一个adlist.h/listNode结构表示:
typedef struct listNode
{
struct listNode *prev;//前置节点
struct listNode *next;//后置节点
void *value;//节点的值,注意这里是用 void *,即可以接收任何类型的值。
}listNode;
多个listNode可以通过prev和next组成双端链表。
Redis中又使用adlist.h/list来持有链表。这样的好处就是操作更加方便。
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;
list结构为整个双端链表提供了头指针head、尾指针tail,链表长度len,而dup、free、match成员现在看来我并不明白是什么意思。书中解释到是用于实现多态链表所需的类型特定函数(不理解)。
这里先写出他们各自的作用,留作问题。
dup、free、match作用
dup函数用于复制链表节点保存的值
free函数用于释放链表节点保存的值
match函数用于比较链表节点保存的值和另一个输入值是否相等。
list结构持有三个listNode结构组成的链表形式
有了list结构持有,整个双端链表一目了然,比如可以迅速找到头指针,以复杂度O(1)获得链表长度等。
Redis的链表实现特性
双端:每个节点带有prev和next指针,获取某个节点的前置和后置节点复杂度都为O(1)。
无环:表头结点prev指针和表尾结点next指针都指向NULL,链表以NULL为终点。
表头和表尾指针:获取头尾结点位置的复杂度尾O(1)。
链表长度计数器:len使得获取链表长度复杂度为O(1)。
多态:链表结点用void *指针来保存结点值,可以通过list结构的dup,free,match为节点值设置类型特定函数,故链表可以保存各种不同的值。
链表和链表节点的API