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

作为一种常用数据结构,链表内置在很多高级编程语言里, 因为 C 语言没有内置这种数据结构, Redis 构建了自己的链表实现.

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

对于链表的定义和相关算法,很多算法书籍已经做了详细的讲解.这里只对 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基本数据结构】链表实现》

链表实现特性

Redis 的链表实现特性可以总结如下:

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

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

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

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

  • 多态: 链表节点使用 void * 指针来保存节点值, 并且可以通过 list 结构的 dupfreematch 三个属性为节点值设置类型特定函数.链表可以用于保存各种不同类型的值.

我的博客: http://ygmyth.github.io

    原文作者:ygmyth
    原文地址: https://segmentfault.com/a/1190000004847677
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞