redis源码学习--数据结构:链表

redis源码学习–数据结构之链表

redis中的链表介绍

redis中使用的是双向链表,定义在目录src\adlist.c中,结构体定义在同名的头文件中。
src\adlist.c封装了链表的API

链表的结构分表头和节点。
表头结构如下:
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;

除了指向链表首尾的指针,还声明了拷贝、清理内存和匹配的接口。这些接口都可以根据具体的链表具体定义。

节点的结构定义就是常规的双向链表的结构
typedef struct listNode {
struct listNode *prev;
struct listNode *next;
void *value;
} listNode;

特别的为了方便操作链表,定义了迭代器的结构:
typedef struct listIter {
listNode *next;
int direction;
} listIter;

下面介绍下拷贝链表操作来说明引入迭代器的便利:

void listRewind(list *list, listIter *li) {
    li->next = list->head;
    li->direction = AL_START_HEAD;
}

listNode *listNext(listIter *iter)
{
    listNode *current = iter->next;

    if (current != NULL) {
        if (iter->direction == AL_START_HEAD)
            iter->next = current->next;
        else
            iter->next = current->prev;
    }
    return current;
}

list *listDup(list *orig)
{
    list *copy;
    listIter iter;
    listNode *node;

    if ((copy = listCreate()) == NULL)
        return NULL;
    copy->dup = orig->dup;
    copy->free = orig->free;
    copy->match = orig->match;
    listRewind(orig, &iter); // 使用迭代器指向链表头
    while((node = listNext(&iter)) != NULL) { // 检查是否到达链表尾
        void *value;

        if (copy->dup) {
            value = copy->dup(node->value); // 使用自定义的拷贝函数拷贝节点内存
            if (value == NULL) {
                listRelease(copy);
                return NULL;
            }
        } else
            value = node->value;
        if (listAddNodeTail(copy, value) == NULL) {
            listRelease(copy);
            return NULL;
        }
    }
    return copy;
}

总结:
redis使用的是双向链表,表头结构声明了拷贝,释放,匹配三种方式,以及引入了迭代器的定义,值得学习。

你可能感兴趣的:(数据结构(C语言):链表)