【Redis基本数据结构】链表实现


做为一种经常使用数据结构,链表内置在不少高级编程语言里, 由于 C 语言没有内置这种数据结构, Redis 构建了本身的链表实现.git

链表在 Redis 中的应用十分普遍, 好比列表键的底层实现之一就是链表. 当一个列表键包含了数量较多的元素,或者列表中包含的元素都是比较长的字符串时, Redis 就会使用链表做为列表键的底层实现.
<!-- more -->
除了列表键以外, 发布与订阅、慢查询、监视器等功能也用到了链表.还有使用链表来构建客户端输出缓冲区等.github

对于链表的定义和相关算法,不少算法书籍已经作了详细的讲解.这里只对 Redis 中链表的实现作介绍.算法

链表和链表节点的实现

每一个链表节点使用一个 listNode 结构来表示:编程

// file: adlist.h
typedef struct listNode {
    struct listNode *prev;  // 前置节点
    struct listNode *next;  //后置节点
    void *value;            //节点的值
} ListNode;

多个链表节点经过 prevnext 组成双端链表,
Redis 使用 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;

下图是由一个 lsit 结构和三个 ListNode 结构组成的链表.编程语言

此处输入图片的描述

链表实现特性

Redis 的链表实现特性能够总结以下:函数

  • 双端: 由于带有 prevnext 指针,获取某个节点的前置节点和后置节点的复杂度都是$O(1)$spa

  • 无环: 表头的 prev 指针和表尾的 next 指针均指向 NULL, 对链表的访问以 NULL 结束.指针

  • 带表头指针和表尾指针: 经过 list 结构获取表头和表尾的复杂度为$ O(1)$.code

  • 带链表长度计数器: list 结构的 len 属性对链表节点的长度计数, 获取链表中节点的数量复杂度为$ O(1)$

  • 多态: 链表节点使用 void * 指针来保存节点值, 而且能够经过 list 结构的 dupfreematch 三个属性为节点值设置类型特定函数.链表能够用于保存各类不一样类型的值.

个人博客: http://ygmyth.github.io

相关文章
相关标签/搜索