本文摘自PHP中文网,作者尚,侵删。

adlist作为Redis中的双端链表,在Redis中被广泛的应用到了很多地方,比如 slowlog的存储,主从复制中报错客户端,list数据结构的实现等,很多都与此相关,所以也是非常重要的一个数据结构。
一)、Redis中双端链表的数据结构
(推荐:redis视频教程)
双端链表(以下代码定义在 src/adlist.h):
1 2 3 4 5 6 7 8 9 | 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;
|
双端链表的节点(以下代码定义在 src/adlist.h):
1 2 3 4 5 | typedef struct listNode {
struct listNode *prev;
struct listNode *next;
void *value;
} listNode;
|

list 通过 head 和 tail两个指针分别指向链表的头尾两端,使得遍历链表可以从正反两个顺序进行遍历,而 listNode 的void *value,则可以保存任意数据,并可以通过dup,free,match来自定义如何处理listNode的值。
二、双端链表的简单操作
创建链表(以下代码定义在 src/adlist.c):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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;
}
|
追加到链表结尾(以下代码定义在 src/adlist.c):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | 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;
}
|
遍历链表:
常用的遍历链表有两种方式,一个是根据链表长度通过while循环去手动遍历,还有一种是用Redis双端链表提供的迭代器来遍历。
手动遍历(以下代码定义在 src/adlist.c 中的 内存释放函数):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | 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);
}
|
迭代器方式遍历请见下文。
三)、双端链表的迭代器
Redis 为了方便对链表的迭代,对链表进行了迭代器的封装,迭代器结构如下(以下代码定义在 src/adlist.h):
1 2 3 4 5 6 | typedef struct listIter {
listNode *next;
int direction;
} listIter;
|
迭代器使用实例:
1 2 3 4 5 6 7 8 | iter = listGetIterator(l, AL_START_HEAD);
while ((n = listNext(iter))) {
printf( "Node Value: %s\n" , listNodeValue(n));
}
|
更多redis知识请关注redis入门教程栏目。
以上就是Redis中的双端链表实现的详细内容,更多文章请关注木庄网络博客!
相关阅读 >>
Redis主从复制
Redis缓存怎么和数据库同步
Redis有多少个库
Redis的hash怎么实现的
Redis为什么要序列化
laradock 如何添加 Redis 配置
Redis作用有哪些
Redis缓存雪崩、缓存击穿、缓存穿透是什么意思
Redis分布式锁的正确实现方式介绍
windows下搭建Redis集群示例
更多相关阅读请进入《Redis》频道 >>
机械工业出版社
本书主要讲述了数据模型、基于对象的数据库和XML、数据存储和查询、事务管理、体系结构等方面的内容。
转载请注明出处:木庄网络博客 » Redis中的双端链表实现