美文网首页面试题之算法知识
redis双向链表实现(3)

redis双向链表实现(3)

作者: lmem | 来源:发表于2017-05-20 12:23 被阅读26次

链表(list)是Redis中最基本的数据结构, 由adlist.h和adlist.c定义
事务模块使用双端链表依序保存输入的命令; 服务器模块使用双端链表来保存多个客户端; 订阅/发送模块使用双端链表来保存订阅模式的多个客户端; 事件模块使用双端链表来保存时间事件(time event);

1.数据类型

//节点
typedef struct listNode {
    struct listNode *prev;
    struct listNode *next;
    void *value;
} listNode;

//迭代对象
typedef struct listIter {
    listNode *next;
    int direction;
} listIter;

//链表
typedef struct list {
    listNode *head;
    listNode *tail;
    void *(*dup)(void *ptr);//复制(dup)
    void (*free)(void *ptr);//释放(free)
    int (*match)(void *ptr, void *key);//匹配(match)
    unsigned long len;
} list;

2.基本操作

(1)复制释放匹配函数手动复制

#define listSetDupMethod(l,m) ((l)->dup = (m))
#define listSetFreeMethod(l,m) ((l)->free = (m))
#define listSetMatchMethod(l,m) ((l)->match = (m))

(2)迭代器

//获得迭代器对象
listIter *listGetIterator(list *list, int direction)
{
    listIter *iter;

    if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
    if (direction == AL_START_HEAD)
        iter->next = list->head;
    else
        iter->next = list->tail;
    iter->direction = direction;
    return iter;
}

//释放迭代器对象
/* Release the iterator memory */
void listReleaseIterator(listIter *iter) {
    zfree(iter);
}

/* Create an iterator in the list private iterator structure */
//重新指向链表头
void listRewind(list *list, listIter *li) {
    li->next = list->head;
    li->direction = AL_START_HEAD;
}

//重新指向迭代器的尾部
void listRewindTail(list *list, listIter *li) {
    li->next = list->tail;
    li->direction = AL_START_TAIL;
}

/* Return the next element of an iterator.
 * It's valid to remove the currently returned element using
 * listDelNode(), but not to remove other elements.
 *
 * The function returns a pointer to the next element of the list,
 * or NULL if there are no more elements, so the classical usage patter
 * is:
 *
 * iter = listGetIterator(list,<direction>);
 * while ((node = listNext(iter)) != NULL) {
 *     doSomethingWith(listNodeValue(node));
 * }
 *
 * */
//!!!!遍历迭代器
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;
}

(3)基本操作

/创建list,分配内存
list *listCreate(void)
{
    struct list *list;

    if ((list = zmalloc(sizeof(*list))) == NULL)
        return NULL;
    list->head = list->tail = NULL;
    list->len = 0;
    list->dup = NULL;
    list->free = NULL;
    list->match = NULL;
    return list;
}

/* Free the whole list.
 *
 * This function can't fail. */
//释放list
void listRelease(list *list)
{
    unsigned long len;
    listNode *current, *next;

    current = list->head;
    len = list->len;
    //先释放节点内存
    while(len--) {
        next = current->next;
        if (list->free) list->free(current->value);
        zfree(current);
        current = next;
    }
    //再释放链表内存
    zfree(list);
}

/* Add a new node to the list, to head, containing the specified 'value'
 * pointer as value.
 *
 * On error, NULL is returned and no operation is performed (i.e. the
 * list remains unaltered).
 * On success the 'list' pointer you pass to the function is returned. */
//在链表头增加一个节点
list *listAddNodeHead(list *list, void *value)
{
    listNode *node;

    if ((node = zmalloc(sizeof(*node))) == NULL)
        return NULL;
    node->value = value;
    if (list->len == 0) {
        list->head = list->tail = node;
        node->prev = node->next = NULL;
    } else {
        node->prev = NULL;
        node->next = list->head;
        list->head->prev = node;
        list->head = node;
    }
    list->len++;
    return list;
}
//复制双向链表
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语言是一个比较底层的语言,库内没有实现链表,于是Redis自己实现了链表。Redis的链表是一个双向链表。 ...

  • redis双向链表实现(3)

    链表(list)是Redis中最基本的数据结构, 由adlist.h和adlist.c定义事务模块使用双端链表依序...

  • Redis底层数据结构之双端链表

    前言 Redis的双端链表是基于双向链表实现的,但传统双向链表存在一些问题,比如获取链表长度需要遍历整个链表,时间...

  • 9.双向链表DoubleLinkList

    目录:1.双向链表的定义2.双向链表的图解3.双向链表定义操作4.双向链表的实现 1.双向链表的定义 2.双向链表...

  • [redis 源码走读] 链表

    redis 的链表实现不是很复杂,从 listNode 可以知道,list 是一个双向链表,支持从链表首尾两边开始...

  • 双向链表python实现

    python 双向链表实现 双向链表实现 链表头部添加 链表尾部添加 插入 删除 查询结点

  • redis链表

    redis链表 作用:实现list命令 作为redis定时事件的实现方式 服务器保存客户端列表等 数据结构 双向非...

  • 吊打面试官之 Java Web [3]

    1.请问redis的List能在什么场景下使用? 参考回答: Redis 中list的数据结构实现是双向链表,所以...

  • Redis消息队列&发布订阅模式使用

    Redis实现消息队列原理 Redis的列表是使用双向链表实现的,保存了头尾节点,在列表头尾两边插取元素是非常...

  • quicklist.c

    Redis的quicklist是一种基于ziplist实现的可压缩(quicklistLZF)的双向链表,结合了链...

网友评论

    本文标题:redis双向链表实现(3)

    本文链接:https://www.haomeiwen.com/subject/mqtpxxtx.html