redis源码-----链表
Posted king哥Java架构
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis源码-----链表相关的知识,希望对你有一定的参考价值。
链表提供了高效的节点重排能力,以及顺序性节点访问方式,并且可以通过增删节点来灵活的调整链表的长度。redis使用的C语言中并没有内置这种数据结构,redis构建了自己的链表实现。当一个列表键包含了数量比较多的元素,又或者列表中包含的元素都是比较长的字符串时候,redis就会使用链表作为列表键的底层实现。
节点的结构
typedef struct listNode {
struct listNode *prev;
struct listNode *next;
void *value; } listNode;
多个listNode通过prev和next两个指针构成一个双向链表。
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;
redis中链表特性总结
- 双端:链表节点都带有两个指针,prev和next,这样获取一个节点的前置和后置节点的时间复杂度都是O(1)。
- 无环:表头的prev指针和表尾的next指针都只想NULL,对链表的访问以NULL为终点。
- 带有表头节点和表尾节点的指针:获取表头和表尾节点的复杂度是O(1)。
- 带有长度计数器:方便获取链表的长度复杂度为O(1)。
- 多态:链表节点使用void*指针来保存节点值,可以用于宝顿各种不同类型的值。
如果你觉得自己学习效率低,缺乏正确的指导,可以加入资源丰富,学习氛围浓厚的技术圈一起学习交流吧!
[Java架构群]
群内有许多来自一线的技术大牛,也有在小厂或外包公司奋斗的码农,我们致力打造一个平等,高质量的JAVA交流圈子,不一定能短期就让每个人的技术突飞猛进,但从长远来说,眼光,格局,长远发展的方向才是最重要的。
源码分析start
创建一个不包含任何节点的链表:listCreate
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;
}
将所有节点都置空,不会毁掉这个list:listEmpty
void listEmpty(list *list)
{
unsigned long len;
listNode *current, *next;
current = list->head;
len = list->len;
//循环去利用当前list的free函数去释放节点
while(len--) {
next = current->next;
if (list->free) list->free(current->value);
zfree(current);
current = next;
}
list->head = list->tail = NULL;
list->len = 0;
}
利用迭代器去遍历list:
//listIter是指针加上方向
typedef struct listIter {
listNode *next;
int direction;
} listIter;
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;
}
链表的查询:listSearchKey
listNode *listSearchKey(list *list, void *key)
{
listIter iter;
listNode *node;
listRewind(list, &iter);
while((node = listNext(&iter)) != NULL) {
//如果设定了比较函数,就用设定的函数进行比较。否则就是直接比较指针
if (list->match) {
if (list->match(node->value, key)) {
return node;
}
} else {
if (key == node->value) {
return node;
}
}
}
return NULL;
}
删除节点:listDelNode
void listDelNode(list *list, listNode *node)
{
//如果不是头节点
if (node->prev)
//当前节点的prev节点的next指向当前节点的next节点
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);
//当前列表长度减1
list->len--;
}
头节点尾节点互换:listRotate
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;
}
列表的连接:listJoin
void listJoin(list *l, list *o) {
if (o->head)
o->head->prev = l->tail;
if (l->tail)
l->tail->next = o->head;
else
l->head = o->head;
if (o->tail) l->tail = o->tail;
l->len += o->len;
/* Setup other as an empty list. */
o->head = o->tail = NULL;
o->len = 0;
}
最后
给大家分享一篇一线开发大牛整理的java高并发核心编程神仙文档,里面主要包含的知识点有:多线程、线程池、内置锁、JMM、CAS、JUC、高并发设计模式、Java异步回调、CompletableFuture类等。
码字不易,如果觉得本篇文章对你有用的话,请给我一键三连!关注作者,后续会有更多的干货分享,请持续关注!
以上是关于redis源码-----链表的主要内容,如果未能解决你的问题,请参考以下文章