[redis源码注释]-双向链表

[redis源码注释]-双向链表

second60 20180511

1. 双向链表源文件

头文件:adlist.h

C文件:adlist.c

 

2. 双向链表结构定义

2.1 链表节点

typedef  struct  listNode
{
struct  listNode * prev;
struct  listNode * next;
void * value;
}listNode;

分析:

这是一个标准的双向链表结构,包含一个前节点指针和后节点指针,同时包含一个void* 可以容纳任务类型。

 

2.2 链表头部

typedef  struct  list
{
struct  listNode * head; // 第一个节点指针
struct  listNode * tail ;// 最后一个节点指针
unsigned  long  len;// 节点长度
void *(*dump)(void *value);
void  (*free)(void *value);
void  (*match)(void *value);
}list;

分析:

1. 头部包含头节点和尾节点指针,方便使用,如使用尾节点,不用遍历一最后,直接使用

2. len 表示节点现有的长度,取长度时,不用遍历即可知道,时间复杂度O(1)

3. 包含dump/free/match三上节点值处理函数。因为节点值不同,所以处理方法可能不同,采用函数指针的可以动态地指针处理的具体函数。不指定,则不使用。

 

总结:

链表头部,是双端链表算法优化的地方,添加了尾节点指针,长度,和三个动态装载的函数。算法的大部分函数复杂度为O(1)O(n),效率非常高。

 

双端链表结构图:

 

 

2.3 链表迭代指针

typedef  struct  listIter
{
listNode  *next;
int  direction;
}listIter;

分析:

1. 迭化器包含了当前遍历到的节点指针

2. 同时添加了direction来判断遍历是向前还是向后

3. 迭代器可以非常方便地遍历链表

 

3.  adlist.h文件

#ifndef __ADLIST_H__

#define __ADLIST_H__

 

/* Node, List, and Iterator are the only data structures used currently. */

 

/*

 * 双端链表节点

 */

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);

    // 节点值释放函数

    void (*free)(void *ptr);

    // 节点值对比函数

    int (*match)(void *ptr, void *key);

 

    // 上面三个函指针的目的是为了动态去设置具体的节点值操作函数,

    // 因为链表中的值可能是不同内容的,所以每个链表的值

    // 都可能有不同的函数去操作

    // 如果没有设置,则不操作,看后面的函数可知

 

    // 链表所包含的节点数量

    unsigned long len;

 

} list;

 

/* Functions implemented as macros */

// 返回给定链表所包含的节点数量

// T = O(1)

#define listLength(l) ((l)->len)

// 返回给定链表的表头节点

// T = O(1)

#define listFirst(l) ((l)->head)

// 返回给定链表的表尾节点

// T = O(1)

#define listLast(l) ((l)->tail)

// 返回给定节点的前置节点

// T = O(1)

#define listPrevNode(n) ((n)->prev)

// 返回给定节点的后置节点

// T = O(1)

#define listNextNode(n) ((n)->next)

// 返回给定节点的值

// T = O(1)

#define listNodeValue(n) ((n)->value)

 

// 将链表 l 的值复制函数设置为 m

// T = O(1)

#define listSetDupMethod(l,m) ((l)->dup = (m))

// 将链表 l 的值释放函数设置为 m

// T = O(1)

#define listSetFreeMethod(l,m) ((l)->free = (m))

// 将链表的对比函数设置为 m

// T = O(1)

#define listSetMatchMethod(l,m) ((l)->match = (m))

 

// 返回给定链表的值复制函数

// T = O(1)

#define listGetDupMethod(l) ((l)->dup)

// 返回给定链表的值释放函数

// T = O(1)

#define listGetFree(l) ((l)->free)

// 返回给定链表的值对比函数

// T = O(1)

#define listGetMatchMethod(l) ((l)->match)

 

/* Prototypes */

list *listCreate(void);

void listRelease(list *list);

list *listAddNodeHead(list *list, void *value);

list *listAddNodeTail(list *list, void *value);

list *listInsertNode(list *list, listNode *old_node, void *value, int after);

void listDelNode(list *list, listNode *node);

listIter *listGetIterator(list *list, int direction);

listNode *listNext(listIter *iter);

void listReleaseIterator(listIter *iter);

list *listDup(list *orig);

listNode *listSearchKey(list *list, void *key);

listNode *listIndex(list *list, long index);

void listRewind(list *list, listIter *li);

void listRewindTail(list *list, listIter *li);

void listRotate(list *list);
/* Directions for iterators
 *
 * 迭代器进行迭代的方向
 */

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

4.  adlist.c文件

 

#include <stdlib.h>

#include "adlist.h"

#include "zmalloc.h"

 

/* Create a new list. The created list can be freed with

 * AlFreeList(), but private value of every node need to be freed

 * by the user before to call AlFreeList().

 *

 * On error, NULL is returned. Otherwise the pointer to the new list. */

/*

 * 创建一个新的链表

 *

 * 创建成功返回链表,失败返回 NULL 。

 *

 * T = O(1)

 */

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

/*

 * 释放整个链表,以及链表中所有节点

 *

 * T = O(N)

 */

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, contaning 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. */

/*

 * 将一个包含有给定值指针 value 的新节点添加到链表的表头

 *

 * 如果为新节点分配内存出错,那么不执行任何动作,仅返回 NULL

 *

 * 如果执行成功,返回传入的链表指针

 *

 * T = O(1)

 */

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为空

        // 链表尾中的最后一个节点的node->next也为空

        node->prev = NULL;

        node->next = list->head;

        // 把之前第一个节点的prev设为node

        list->head->prev = node;

        // 把list->head设为node

        list->head = node;

    }

 

    // 更新链表节点数

    list->len++;

 

    return list;

}

 

/* Add a new node to the list, to tail, 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. */

/*

 * 将一个包含有给定值指针 value 的新节点添加到链表的表尾

 *

 * 如果为新节点分配内存出错,那么不执行任何动作,仅返回 NULL

 *

 * 如果执行成功,返回传入的链表指针

 *

 * T = O(1)

 */

list *listAddNodeTail(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 = list->tail;

        node->next = NULL;

        list->tail->next = node;

        list->tail = node;

    }

 

    // 更新链表节点数

    list->len++;

 

    return list;

}

 

/*

 * 创建一个包含值 value 的新节点,并将它插入到 old_node 的之前或之后

 *

 * 如果 after 为 0 ,将新节点插入到 old_node 之前。

 * 如果 after 为 1 ,将新节点插入到 old_node 之后。

 *

 * T = O(1)

 */

list *listInsertNode(list *list, listNode *old_node, void *value, int after) {

    listNode *node;

 

    // 创建新节点

    if ((node = zmalloc(sizeof(*node))) == NULL)

        return NULL;

 

    // 保存值

    node->value = value;

 

    // 将新节点添加到给定节点之后

    if (after) {

        node->prev = old_node;

        node->next = old_node->next;

        // 给定节点是原表尾节点

        if (list->tail == old_node) {

            list->tail = node;

        }

    // 将新节点添加到给定节点之前

    } else {

        node->next = old_node;

        node->prev = old_node->prev;

        // 给定节点是原表头节点

        if (list->head == old_node) {

            list->head = node;

        }

    }

 

    // 更新新节点的前置指针

    if (node->prev != NULL) {

        node->prev->next = node;

    }

    // 更新新节点的后置指针

    if (node->next != NULL) {

        node->next->prev = node;

    }

 

    // 更新链表节点数

    list->len++;

 

    return list;

}

 

/* Remove the specified node from the specified list.

 * It's up to the caller to free the private value of the node.

 *

 * This function can't fail. */

/*

 * 从链表 list 中删除给定节点 node

 *

 * 对节点私有值(private value of the node)的释放工作由调用者进行。

 *

 * T = O(1)

 */

void listDelNode(list *list, listNode *node)

{

    // 调整前置节点的指针

    if (node->prev)

        node->prev->next = node->next;

    else

        list->head = node->next;

 

    // 调整后置节点的指针

    if (node->next)

        node->next->prev = node->prev;

    else

        list->tail = node->prev;

 

    // 释放值

    if (list->free) list->free(node->value);

 

    // 释放节点

    zfree(node);

 

    // 链表数减一

    list->len--;

}

 

/* Returns a list iterator 'iter'. After the initialization every

 * call to listNext() will return the next element of the list.

 *

 * This function can't fail. */

/*

 * 为给定链表创建一个迭代器,

 * 之后每次对这个迭代器调用 listNext 都返回被迭代到的链表节点

 *

 * direction 参数决定了迭代器的迭代方向:

 *  AL_START_HEAD :从表头向表尾迭代

 *  AL_START_TAIL :从表尾想表头迭代

 *

 * T = O(1)

 */

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 */

/*

 * 释放迭代器

 *

 * T = O(1)

 */

void listReleaseIterator(listIter *iter) {

    zfree(iter);

}

 

/* Create an iterator in the list private iterator structure */

/*

 * 将迭代器的方向设置为 AL_START_HEAD ,

 * 并将迭代指针重新指向表头节点。

 *

 * T = O(1)

 */

void listRewind(list *list, listIter *li) {

    li->next = list->head;

    li->direction = AL_START_HEAD;

}

 

/*

 * 将迭代器的方向设置为 AL_START_TAIL ,

 * 并将迭代指针重新指向表尾节点。

 *

 * T = O(1)

 */

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));

 * }

 *

 * */

/*

 * 返回迭代器当前所指向的节点。

 *

 * 删除当前节点是允许的,但不能修改链表里的其他节点。

 *

 * 函数要么返回一个节点,要么返回 NULL ,常见的用法是:

 *

 * iter = listGetIterator(list,<direction>);

 * while ((node = listNext(iter)) != NULL) {

 *     doSomethingWith(listNodeValue(node));

 * }

 *

 * T = O(1)

 */

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;

}

 

/* Duplicate the whole list. On out of memory NULL is returned.

 * On success a copy of the original list is returned.

 *

 * The 'Dup' method set with listSetDupMethod() function is used

 * to copy the node value. Otherwise the same pointer value of

 * the original node is used as value of the copied node.

 *

 * The original list both on success or error is never modified. */

/*

 * 复制整个链表。

 *

 * 复制成功返回输入链表的副本,

 * 如果因为内存不足而造成复制失败,返回 NULL 。

 *

 * 如果链表有设置值复制函数 dup ,那么对值的复制将使用复制函数进行,

 * 否则,新节点将和旧节点共享同一个指针。

 *

 * 无论复制是成功还是失败,输入节点都不会修改。

 *

 * T = O(N)

 */

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;

 

    // 迭代整个输入链表

    iter = listGetIterator(orig, AL_START_HEAD);

    while((node = listNext(iter)) != NULL) {

        void *value;

 

        // 复制节点值到新节点

        if (copy->dup) {

            value = copy->dup(node->value);

            if (value == NULL) {

                listRelease(copy);

                listReleaseIterator(iter);

                return NULL;

            }

        } else

            value = node->value;

 

        // 将节点添加到链表

        if (listAddNodeTail(copy, value) == NULL) {

            listRelease(copy);

            listReleaseIterator(iter);

            return NULL;

        }

    }

 

    // 释放迭代器

    listReleaseIterator(iter);

 

    // 返回副本

    return copy;

}

 

/* Search the list for a node matching a given key.

 * The match is performed using the 'match' method

 * set with listSetMatchMethod(). If no 'match' method

 * is set, the 'value' pointer of every node is directly

 * compared with the 'key' pointer.

 *

 * On success the first matching node pointer is returned

 * (search starts from head). If no matching node exists

 * NULL is returned. */

/*

 * 查找链表 list 中值和 key 匹配的节点。

 *

 * 对比操作由链表的 match 函数负责进行,

 * 如果没有设置 match 函数,

 * 那么直接通过对比值的指针来决定是否匹配。

 *

 * 如果匹配成功,那么第一个匹配的节点会被返回。

 * 如果没有匹配任何节点,那么返回 NULL 。

 *

 * T = O(N)

 */

listNode *listSearchKey(list *list, void *key)

{

    listIter *iter;

    listNode *node;

 

    // 迭代整个链表

    iter = listGetIterator(list, AL_START_HEAD);

    while((node = listNext(iter)) != NULL) {

        

        // 对比

        if (list->match) {

            if (list->match(node->value, key)) {

                listReleaseIterator(iter);

                // 找到

                return node;

            }

        } else {

            if (key == node->value) {

                listReleaseIterator(iter);

                // 找到

                return node;

            }

        }

    }

    

    listReleaseIterator(iter);

 

    // 未找到

    return NULL;

}

 

/* Return the element at the specified zero-based index

 * where 0 is the head, 1 is the element next to head

 * and so on. Negative integers are used in order to count

 * from the tail, -1 is the last element, -2 the penultimate

 * and so on. If the index is out of range NULL is returned. */

/*

 * 返回链表在给定索引上的值。

 *

 * 索引以 0 为起始,也可以是负数, -1 表示链表最后一个节点,诸如此类。

 *

 * 如果索引超出范围(out of range),返回 NULL 。

 *

 * T = O(N)

 */

listNode *listIndex(list *list, long index) {

    listNode *n;

 

    // 如果索引为负数,从表尾开始查找

    if (index < 0) {

        index = (-index)-1;

        n = list->tail;

        while(index-- && n) n = n->prev;

    // 如果索引为正数,从表头开始查找

    } else {

        n = list->head;

        while(index-- && n) n = n->next;

    }

 

    return n;

}

 

/* Rotate the list removing the tail node and inserting it to the head. */

/*

 * 取出链表的表尾节点,并将它移动到表头,成为新的表头节点。

 *

 * T = O(1)

 */

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;

}

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值