redis之adlist
来源:互联网 发布:订单制作软件 编辑:程序博客网 时间:2024/05/25 19:56
号外号外,新建Redis交流讨论群:332160890,欢迎加入!!
类型介绍
这部分是redis自定义的链表类型,该链表为双向链表,可以自定义存储类型,另外可以自定义释放、拷贝、对比函数等功能,提供的操作也比较丰富,包括创建、添加、插入、删除、索引等步骤,还拥有迭代器功能。
代码分析
自定义类型
链表节点,双向链表
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); //自定义释放空间函数,用于释放value占用空间 int (*match)(void *ptr, void *key); //自定义比较函数 unsigned long len; //链表长度} list;
定义变量
代码分解
listCreate,创建一个链表,内部不存储元素,创建失败返回NULL;
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;}
listRelease,释放链表,由于每个元素都是实际分配的内存,必须使用zfree函数释放;
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); //释放当前value占用的内存 zfree(current); //释放该节点结构体占用的内存空间 current = next; } zfree(list);}
listAddNodeHead,在链表头部添加一个value,分配一个节点放置在链表头;
list *listAddNodeHead(list *list, void *value){ listNode *node; if ((node = zmalloc(sizeof(*node))) == NULL) return NULL; //申请内存 node->value = value; //这里是不是该判断下list是否为NULL ? 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的头节点设置为该节点 } list->len++; return list; //返回之前传入的链表指针}
listAddNodeTail,为当前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;}
listInsertNode,插入某个value,分配该节点插入到old_node前后,after来表示前后方向;
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; //如果old_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;}
listDelNode,删除某个节点;
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); //如果有自定义内存释放函数,调用去释放节点的value信息 zfree(node); //释放该节点 list->len--;}
listGetIterator,根据设定的方向(正向还是反向)获取迭代器,这类迭代器比较简单,不涉及锁操作;
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;}
listReleaseIterator,释放迭代器内存;
void listReleaseIterator(listIter *iter) { zfree(iter);}
listRewind,为一个迭代器,设置正向;
void listRewind(list *list, listIter *li) { li->next = list->head; li->direction = AL_START_HEAD;}
listRewindTail,为一个迭代器,设置反向;
void listRewindTail(list *list, listIter *li) { li->next = list->tail; li->direction = AL_START_TAIL;}
listNext,根据迭代器获取下一个节点;
listNode *listNext(listIter *iter){ listNode *current = iter->next; if (current != NULL) { if (iter->direction == AL_START_HEAD) iter->next = current->next; //正向,为当前节点的next else iter->next = current->prev; //反向,为当前节点的prev } return current;}
listDup,拷贝一个链表;
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,按key查找;
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; //未找到,返回}
listIndex,获取当前索引对应的节点,从0开始计数;
listNode *listIndex(list *list, long index) { listNode *n; if (index < 0) { //index为负,表示从尾部开始 index = (-index)-1; n = list->tail; while(index-- && n) n = n->prev; } else { //否则从正向开始 n = list->head; while(index-- && n) n = n->next; } return n;}
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;}
0 0
- redis之adlist
- Redis之2-双端链表(adlist.c,adlist.h)
- Redis adlist
- Redis源码-数据结构之Adlist双端链表
- redis源码分析之数据结构(一)链表adlist.c
- redis源码分析(adlist)
- (redis)adlist.h/adlist.c理解
- redis源码分析-adlist(链表)
- Redis源码学习(1):adlist
- Redis源码分析(adlist)
- adlist
- redis源码解读之双向链表————adlist.h文件
- Adlist 双向链表的实现 redis
- 【redis源码分析】双向链表---adlist
- redis源码系列-数据结构(adlist/ziplist/dict)
- redis源码阅读(2)---- adlist分析
- redis学习笔记(2)---链表adlist
- Redis源码阅读笔记—adlist
- C语言的32个关键字
- 第一次运行DirectX项目 ——相关问题解决
- RecyclerView+ImageLoader图片列表的加载与展示【从listview加载图片性能优化引出的解决方法】
- tensorflow 安装问题解决
- JSON for java入门总结
- redis之adlist
- 剑指offer阅读笔记 之面试题19 实现二叉树的镜像 之 又复习一遍二叉树
- 人民币大写在线转换工具
- ios企业版发布
- request.getParameter()、request.getInputStream()和request.getReader()
- 基于Php mysql存储过程的详解
- 腾讯2017暑期实习生编程题-构造回文
- 杭电ACM 1002
- java如何得到GET和POST请求URL和参数列表