博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redis源码剖析(九)—— Redis双链表实现
阅读量:2489 次
发布时间:2019-05-11

本文共 4490 字,大约阅读时间需要 14 分钟。

adlist.h

typedef struct listNode {
struct listNode *prev; struct listNode *next; void *value;} listNode;typedef struct list {
listNode *head; listNode *tail; void *(*dup)(void *ptr); void (*free)(void *ptr); int (*match)(void *ptr, void *key); unsigned int len; listIter iter;} list;

adlist.c

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;}void listRelease(list *list){
unsigned int 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);}/* * 从头结点增加元素,即采用的是头插入法 * 发生错误时将返回NULL */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;}/* * 采用尾插入法向链表中增加元素 * value是向链表中增加的值 * 如果增加失败的话会返回空指针 */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;}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--;} /* * 链表的复制函数 * 复制成功后,返回复制链表的头节点 */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;}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 {
//如果未设置match函数的话 if (key == node->value) {
//直接比较指针里的地址 listReleaseIterator(iter);//释放迭代器所占用的内存空间 return node;//返回链表当前的结点 } } } listReleaseIterator(iter);//释放迭代器所占用的内存空间 return NULL;}/* * 返回指定索引位置的元素 * index表示索引位置,从0开始 * 如果index超了链表的长度NULL将返回 * 负数表示从尾开始算起,即倒数 */listNode *listIndex(list *list, int index) {
listNode *n; //-1表示尾节点 //-2表示的是尾节点的下一个节点 if (index < 0) {
index = (-index)-1; n = list->tail; while(index-- && n) n = n->prev; } else {
//从头开始进行遍历时0指向head //1指向头节点的下一个元素 n = list->head; while(index-- && n) n = n->next; } //返回索引位置的节点 return n;}

转载地址:http://kkorb.baihongyu.com/

你可能感兴趣的文章
spring cloud zuul网关上传大文件
查看>>
springboot+mybatis日志显示SQL
查看>>
工作流中文乱码问题解决
查看>>
maven打包本地依赖包
查看>>
spring boot jpa 实现拦截器
查看>>
jenkins + maven+ gitlab 自动化部署
查看>>
Pull Request流程
查看>>
Lambda 表达式
查看>>
函数式数据处理(一)--流
查看>>
java 流使用
查看>>
java 用流收集数据
查看>>
java并行流
查看>>
CompletableFuture 组合式异步编程
查看>>
mysql查询某一个字段是否包含中文字符
查看>>
Java中equals和==的区别
查看>>
JVM内存管理及GC机制
查看>>
Java:按值传递还是按引用传递详细解说
查看>>
Java中Synchronized的用法
查看>>
阻塞队列
查看>>
linux的基础知识
查看>>