简介
redis 源码版本:3.05.04
如有理解不对的地方,欢迎各位指出,大家共同交流和学习。
源码学习
结构定义
链表作为一种常用的数据结构,提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度。 链表节点结构:
typedef struct listNode {
struct listNode *prev;
struct listNode *next;
void *value;
} listNode;
示意图如下所示:
为什么listNode结构就可以组成一个双向链表,为什么还要有list结构那?
因为,新增的dup、free、match、len四个字段可以用来实现多态链表所需的数据类型,使用list结构来持有链表的话,操作起来更方便。 链表迭代器结构:
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);
PORT_ULONG len;
} list;
示意图如下所示: redis就是采用这种结构。
创建链表函数
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;
}
释放链表函数
在进行节点空间释放时,先将下一个节点的指针保存到next变量中,然后释放当前节点空间,然后,再将next变量中下一个节点的指针赋值给当前节点。
void listRelease(list *list)
{
PORT_ULONG 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);
}
新增节点到表头函数
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;
}
例:在由3-》4-》-》5组成的链表的表头中,新增一个值为7的节点
新增节点到表尾函数
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;
}
例:在由3-》4-》-》5组成的链表的表尾中,新增一个值为7的节点
|