Redis学习笔记——ListNode

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

typedef struct listNode {

    // 前置节点
    struct listNode *prev;

    // 后置节点
    struct listNode *next;

    // 节点的值
    void *value;

} listNode;

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

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

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

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;

这样定义的好处有:redis

  1. 快速获取链表的头尾算法

  2. 快速查询链表的节点数,像动态字符串sdshr里的len那样,不用遍历所有字符就能够获取字符串的长度,这里也相似。函数

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

typedef struct listIter {

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

    // 迭代的方向
    int direction;

} listIter;

里面迭代的方向为指针

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

迭代器能够经过如下几个接口来使用(不彻底列出来)code

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...

相关文章
相关标签/搜索