一、linkedlist 简介
由于 C 语言没有内置链表这种数据结构,于是 Redis 构建了自己的链表实现。linkedlist 是一个双端链表,也是 list 数据类型的底层实现之一。当一个 list 包含了数量比较多的元素,又或者 list 中包含的元素都是比较长的字符串时,Redis就会使用 linkedlist 作为 list 的底层实现。当一个 lsit 只包含少量的元素,并且每个 list 要么就是小整数值,要么就是长度比较短的字符串,那么 Redis 就会使用 ziplist 作为 list 的底层实现。
二、linkedlist 结构
每个链表节点使用一个 adlist.h/listNode 结构来表示:
pre 指针指向前一个节点,next 指针指向后一个节点,value 指向当前节点对应的数据对象。
虽然仅仅使用多个 listNode 结构就可以组成链表, 但使用 adlist.h/list 来持有链表的话, 操作起来会更方便:
list 结构为链表提供了表头指针 head、表尾指针 tail,以及链表长度计数器 len,而 dup、free 和 match 成员则是用于实现多态链表所需的类型特定函数:
1、dup 函数用于复制链表节点所保存的值;
2、free 函数用于释放链表节点所保存的值;
3、match 函数则用于对比链表节点所保存的值和另一个输入值是否相等。
双端链表结构图:
三、linkedlist 特性
1、双端链表:带有指向前置节点 prev 和后置节点 next 的指针,获取这两个节点的复杂度为 O(1)
2、无环:表头节点的 prev 和表尾节点的 next 都指向 NULL,对链表的访问以 NULL 结束
3、带表头指针和表尾指针:获取表头节点 head 和表尾节点 tail 的复制度为 O(1)
4、链表长度计数器:带有 len 属性,获取链表长度的复杂度为 O(1)
5、多态:链表节点使用 void* 指针保存节点值,可以保存不同类型的值
缺点:查找效率偏低,只能使用顺序查找
四、总结
双端链表 linkedlist 主要有两个作用:
1、作为 Redis 的 list 数据类型底层实现方法之一;
2、作为通用数据结构可以被其他功能模块使用;
双端链表实现简单,Redis 对双端链表加以改造,添加保存节点长度的字段,以及实现自己的迭代指针,使得一些数据操作变得简单。