Redis学习笔记——ListNode

Redis定义了双向链表,用来存储列表键的值,还有其他的我不知的。
双向链表的节点定义为:

typedef struct listNode {

    // 前置节点
    struct listNode *prev;

    // 后置节点
    struct listNode *next;

    // 节点的值
    void *value;

} listNode;

这里是把节点的值作为了一个成员变量,Linux内核里面节点的定义是这样的

struct list_head{
    struct list_head *next;
    struct list_head *prev;
}

这样可以没有不用处理节点所带数据的类型,但是要通过offsetof/container_of这类来处理。不过这是题外话了。
除此之外,Redis还定义了链表结构,如下:

typedef struct list {

    // 表头节点
    listNode *head;

    // 表尾节点
    listNode *tail;

    // 节点值复制函数
    void *(*dup)(void *ptr);

    // 节点值释放函数
    void (*free)(void *ptr);

    // 节点值对比函数
    int (*match)(void *ptr, void *key);

    // 链表所包含的节点数量
    unsigned long len;

} list;

这样定义的好处有:

  1. 快速获取链表的头尾

  2. 快速查询链表的节点数,像动态字符串sdshr里的len那样,不用遍历全部字符就可以获取字符串的长度,这里也类似。

它里面还定义了链表的迭代器,

typedef struct listIter {

    // 当前迭代到的节点
    listNode *next;

    // 迭代的方向
    int direction;

} listIter;

里面迭代的方向为

// 从表头向表尾进行迭代
#define AL_START_HEAD 0
// 从表尾到表头进行迭代
#define AL_START_TAIL 1

迭代器可以通过以下几个接口来使用(不完全列出来)

listIter *listGetIterator(list *list, int direction) //根据迭代方向给链表创建迭代器
listNode *listNext(listIter *iter) //返回迭代器当前指向的节点,并且把迭代器根据方向向前移动一下

假如我要遍历整个链表,我可以这样做

iter = listGetIterator(list, AL_START_HEAD);
while ((node = listNext(iter)) != NULL) {
    doSomethingWith(node);
}

写起来是比较简单易懂的。
里面还有个反转节点的函数

void listRotate(list *list) {
    listNode *tail = list->tail;

    if (listLength(list) <= 1) return;

    /* Detach current tail */
    // 取出表尾节点
    list->tail = tail->prev;
    list->tail->next = NULL;

    /* Move it as head */
    // 插入到表头
    list->head->prev = tail;
    tail->prev = NULL;
    tail->next = list->head;
    list->head = tail;
}

这个其实是翻转节点,不是倒序。是不是跟以前做过的算法题很像。有没有想起手摇算法。

最后贴上《Redis设计与实现》里的总结

链表被广泛用于实现 Redis 的各种功能, 比如列表键, 发布与订阅, 慢查询, 监视器, 等等。
每个链表节点由一个 listNode 结构来表示, 每个节点都有一个指向前置节点和后置节点的指针, 所以 Redis 的链表实现是双端链表。
每个链表使用一个 list 结构来表示, 这个结构带有表头节点指针、表尾节点指针、以及链表长度等信息。
因为链表表头节点的前置节点和表尾节点的后置节点都指向 NULL , 所以 Redis 的链表实现是无环链表。
通过为链表设置不同的类型特定函数, Redis 的链表可以用于保存各种不同类型的值。

参考:
1.《Redis设计与实现》
2.https://github.com/huangz1990…

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