前言

关于 redis 的数据结构 adlist 

相关介绍主要围绕着如下测试用例, 来看看 adlist 的存储, 以及 相关的 api 

本文的 adlist 相关代码 拷贝自 redis-6.2.0  

代码来自于 https://redis.io/  

 

adlist 这个数据结构映射到 jdk 这边 类似于 java.util.LinkedList 

很多操作 也是链表的基础操作, 呵呵 相当于又温习了一遍 

 

 

测试用例

//
// Created by Jerry.X.He on 2021/2/25.
//

#include<iostream>
#include "../libs/sds.h"
#include "../libs/adlist.h"

using namespace std;

int main(int argc, char **argv) {

    sds head = sdsnew("head");
    sds tail = sdsnew("tail");

    // listCreate
    list *list = listCreate();

    // listAddNodeHead/Tail
    listAddNodeHead(list, head);
    listAddNodeTail(list, tail);

    // listIndex
    listNode *secondEle = listIndex(list, 1);

    // listSearchKey
    listNode *searchedEle = listSearchKey(list, tail);

    // listGetIterator/listNext/listReleaseIterator
    // to head
    listIter *toTailIte = listGetIterator(list, AL_START_HEAD);
    listNode *toTailNode = NULL;
    while ((toTailNode = listNext(toTailIte)) != NULL) {
        cout << (sds) (toTailNode->value) << endl;
    }
    cout << "--------" << endl;

    // to tail
    listIter *toHeadIte = listGetIterator(list, AL_START_TAIL);
    listNode *toHeadNode = NULL;
    while ((toHeadNode = listNext(toHeadIte)) != NULL) {
        cout << (sds) (toHeadNode->value) << endl;
    }
    listReleaseIterator(toHeadIte);
    cout << "--------" << endl;

    // listRewind/listRewindTail
    listRewind(list, toTailIte);
    toTailNode = NULL;
    while ((toTailNode = listNext(toTailIte)) != NULL) {
        cout << (sds) (toTailNode->value) << endl;
    }
    cout << "--------" << endl;

    // listRotate
    listRotateTailToHead(list);
    listRewind(list, toTailIte);
    toTailNode = NULL;
    while ((toTailNode = listNext(toTailIte)) != NULL) {
        cout << (sds) (toTailNode->value) << endl;
    }
    cout << "--------" << endl;

    // listDelNode
    listDelNode(list, secondEle);

    int x = 0;

}

 

 

数据结构

普通的双向链表 

04 关于 adlist_迭代

 

 

listCreate

创建了一个 list 的对象, 并初始化 

04 关于 adlist_迭代_02

 

我们来 inspect 一下 list 

所有的字段都是 NULL/0, 因此 全部都是 0x00 

(lldb) x 0x7fa05f402be0 -c 0x30
0x7fa05f402be0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x7fa05f402bf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x7fa05f402c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

 

 

listAddNodeHead 

新建节点, 并初始化
添加到链表头, 更新 prev, next
更新 list 长度 

04 关于 adlist_linkedlist_03

 

inspect 一下 list, 这里已经是 struct 和 struct 的相关关联, 所以直接查看 变量是可以很清晰的看到链表的相关数据 

这里 list 的 head, tail 均指向 0x7fa05f4023c0, 这个节点的 prev, next 均为 NULL, value 为 "head" 

list 的长度为 1 

04 关于 adlist_adlist_04

 

 

listAddNodeTail

新建节点, 并初始化

添加到链表尾, 更新 prev, next

更新 list 长度

04 关于 adlist_adlist_05

 

inspect 一下 list 

这里 list 的 head 指向的是 0x7fa05f4023c0, tail 均指向 0x7fa05f400450 

节点 0x7fa05f4023c0 的下一个节点是 节点 0x7fa05f400450 

0x7fa05f4023c0 的数据显然就是上面的 "head"

0x7fa05f400450 的数据这里为 "tail"

list 的长度为 2 

此时的 list 中的元素为 "head" -> "tail"

 

 

listIndex

迭代 n 次获取, 对应的 listNode 
n 约定正数从链表头迭代, 负数向链表尾迭代 

可以看到这里的 索引为 1 的元素是 "tail" 

04 关于 adlist_adlist_06

 

 

listSearchKey 

从 list 头迭代到尾部, 比较 listNode 是否匹配给定的 key 
返回匹配的 entry

04 关于 adlist_迭代_07

 

 

listGetIterator 

创建一个迭代器
如果是 从链表头迭代, 初始化 ite->next 为 head, 设置 direction
如果是 从链表尾迭代, 初始化 ite->next 为 tail, 设置 direction

04 关于 adlist_迭代_08

 

listNext

记录 ite->next, 作为结果 result
根据方向 更新 ite->next
返回 result

04 关于 adlist_链表_09

 

listReleaseIterator

04 关于 adlist_linkedlist_10

 

listRewind/listRewindTail 

重置 给定的 iterator 的 next 和 direction 

04 关于 adlist_链表_11

 

 

listRotateTailToHead/listRotateHeadToTail 

一套组合操作

listRotateTailToHead : 将表尾元素移动到表头 

listRotateHeadToTail : 将表头元素移动到表尾 

04 关于 adlist_linkedlist_12

 

 

listDelNode 

移除给定的节点, 更新 next.prev, prev.next, list.head, list.tail 等等 

并释放当前节点, 更新 list.len 

04 关于 adlist_链表_13