链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点灵活的改变链表的长度。
作为一种常用的数据结构,链表内置在很多高级语言中。由于Redis使用的C语言中没有链表,所以Redis构建了自己的链表实现
链表和链表节点的实现
每个链表节点使用adlist.h/listNode结构来表示:
typedef struct listNode {
//前置节点
struct listNode *prev;
//后置节点
struct listNode *next;
//节点的值
void *value;
}listNode;
多个listNode可以通过prev和next相连来组成链表,虽然这样就可以组成链表结构,但使用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结构提供了表头指针和表尾指针,以及链表长度。而dup、free和match成员则是用来实现多态链表所需特定类型的函数:
- dup函数用于复制链表节点的值;
- free函数用于释放链表节点的值;
- match函数用于对比链表节点与另一输入的值是否相等;
Redis的链表实现的特性可以总结如下:
双端:链表节点带有prev和next指针,获取某个节点的前置节点和后续节点的时间复杂度为O(1)。
无环:表头节点的prev和表尾节点的next都指向null,对链表的访问总以null为终点。
带有表头指针和表尾指针:通过list结构的head和tail指针,使得获取表头节点和表尾节点的时间复杂度为O(1)。
带链表长度计数器:通过list结构的len属性来对list持有的节点数量计数,使得获取节点长度的时间复杂度为O(1)。
多态:链表节点使用value指针保存节点的值,并且通过list结构的dup、free和match属性为节点值设置特定函数,使得节点可以保存不同类型的值。
链表和链表节点的API
| 函数 | 作用 | 时间复杂度 |
| listSetDupMethod | 将给定函数设置为链表的节点值复制函数 | O(1),复制函数可以通过链表的dup属性 |
| listGetDupMethod | 返回链表当前使用的节点值复制函数 | O(1) |
| listSetFreeMethod | 将给定函数设置为链表的节点值释放函数 | O(1),释放函数可以通过链表的free属性 |
| listGetFree | 返回链表当前使用的节点值释放函数 | O(1) |
| listSetMatchMethod | 将给定函数设置为链表的节点值对比函数 | O(1),对比函数可以通过链表的match属性 |
| listGetMatchMethod | 返回链表当前使用的节点值对比函数 | O(1) |
| listLength | 返回链表的长度(包含了多少个节点) | O(1),链表长度可以通过链表的len属性直接获得 |
| listFirst | 返回链表的表头节点 | O(1),表头节点可以通过链表的head属性直接获得 |
| listLast | 返回链表的表尾节点 | O(1),表尾节点可以通过链表的tail属性直接获得 |
| listPrevNode | 返回给定节点的前置节点 | O(1),前置节点可以通过节点的prev属性直接获得 |
| listNextNode | 返回给定节点的后置节点 | O(1),后置节点可以通过节点的next属性直接获得 |
| listNodeValue | 返回给定节点正在保存的值 | O(1),节点值可以通过节点的value属性直接获得 |
| listCreate | 创建一个不包含任何节点的新链表 | O(1) |
| listAddNodeHead | 将一个包含给定值的新节点添加到给定链表的表头 | O(1) |
| listAddNodeTail | 将一个包含给定值的新节点添加到给定链表的表尾 | O(1) |
| listInsertNode | 将一个包含给定值的新节点添加到给定节点的之前或者之后 | O(1) |
| listSearchKey | 查找并返回链表中包含给定值的节点 | O(N),N为链表长度 |
| listIndex | 返回链表在给定索引上的节点 | O(N),N为链表长度 |
| listDelNode | 从链表中删除给定节点 | O(N),N为链表长度 |
| listRotate | 将链表的表尾节点弹出,然后将弹出的节点插入到链表的表头,成为新的表头节点 | O(1) |
| listDup | 复制一个给定链表的副本 | O(N),N为链表长度 |
| listRelease | 释放给定链表,以及链表中的所有节点 | O(N),N为链表长度 |
4318

被折叠的 条评论
为什么被折叠?



