Redis中的双端链表的数据结构与操作
发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,今天小编给大家分享的是Redis中的双端链表的数据结构与操作,很多人都不太了解,今天小编为了让大家更加了解Redis中的双端链表,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。adlis
千家信息网最后更新 2025年01月20日Redis中的双端链表的数据结构与操作
今天小编给大家分享的是Redis中的双端链表的数据结构与操作,很多人都不太了解,今天小编为了让大家更加了解Redis中的双端链表,所以给大家总结了以下内容,一起往下看吧。一定会有所收获的哦。
adlist作为Redis中的双端链表,在Redis中被广泛的应用到了很多地方,比如 slowlog的存储,主从复制中报错客户端,list数据结构的实现等,很多都与此相关,所以也是非常重要的一个数据结构。
一)、Redis中双端链表的数据结构
双端链表(以下代码定义在 src/adlist.h):
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):
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):
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):
list *listAddNodeTail(list *list, void *value){ listNode *node; //初始化node节点 //为新的node节点分配内存 if ((node = zmalloc(sizeof(*node))) == NULL) return NULL; //为node节点设置值 node->value = value; if (list->len == 0) { //如果空链表则 将头尾指向 新节点 并后继前驱节点设置为NULL list->head = list->tail = node; node->prev = node->next = NULL; } else { //否则将节点的前驱节点设置为原来的尾部节点 node->prev = list->tail; //由于追加到尾部,后继节点为NULL node->next = NULL; //之前的尾部节点的后继节点设置为新增的节点 list->tail->next = node; //将列表的尾部节点指针指向新增的节点 list->tail = node; } //增加链表长度 list->len++; return list;}
遍历链表:
常用的遍历链表有两种方式,一个是根据链表长度通过while循环去手动遍历,还有一种是用Redis双端链表提供的迭代器来遍历。
手动遍历(以下代码定义在 src/adlist.c 中的 内存释放函数):
void listRelease(list *list){ unsigned long len; //current表示当前遍历的游标指针,next表示下次遍历的游标指针(next作为临时变量用于保存下一个节点) listNode *current, *next; //将current指向头部节点 current = list->head; //计算长度(其实就是 listLength(list)) len = list->len; //通过长度递减的方式进行遍历,便利到长度为0的时候,遍历结束 while(len--) { //保存下次循环的节点指针 next = current->next; //释放掉当前节点,如果设置释放节点的回调函数,则执行用户自定义的函数 if (list->free) list->free(current->value); zfree(current); //将游标指向下个节点 current = next; } zfree(list);}
迭代器方式遍历请见下文。
三)、双端链表的迭代器
Redis 为了方便对链表的迭代,对链表进行了迭代器的封装,迭代器结构如下(以下代码定义在 src/adlist.h):
typedef struct listIter { listNode *next; //迭代器指向的下一个节点 //迭代方向,由于双端链表保存了head和tail的值,所以可以进行两个方向的迭代 //AL_START_HEAD表示从头向后遍历,AL_START_TAIL表示从尾部向前遍历 int direction;} listIter;
迭代器使用实例:
//l表示list结构,n表示listNode结构,listNode的值保存的是sds字符串//创建迭代器对象iter = listGetIterator(l, AL_START_HEAD);//循环获取下一个需要遍历的节点while ((n = listNext(iter))) { //输出返回的节点n的value值 printf("Node Value: %s\n", listNodeValue(n));}
以上就是Redis中的双端链表的数据结构与操作的简略介绍,当然详细使用上面的不同还得要大家自己使用过才领会。如果想了解更多,欢迎关注行业资讯频道哦!
节点
迭代
结构
指向
数据
函数
代码
数据结构
尾部
指针
长度
内存
不同
两个
方式
时候
游标
类型
后继
循环
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
天津统一软件开发服务创意
建钱桥互联网科技有限公司
服务器无响应是运营商的问题吗
ODBC搜不到服务器数据库
登录苹果id账号验证服务器出错
商丘的软件开发公司电话
网络安全的主要收获ppt
web服务器的安全方案
商周互联网科技
云南法院网络安全
店管家服务器繁忙
华顶网络技术有限公司
惠州app软件开发机构
农安通用网络技术服务哪家好
网络道德网络安全案例
兰州外卖软件开发
系统自带虚拟机怎么连接服务器
网络安全大会与左江科技
国家网络安全回答答案
美国专利数据库公司有哪些
微伴网络技术
国外有没有网络安全法
油站平台司机端软件开发
新能源汽车网络技术
正当防卫4老是连不上服务器
农安通用网络技术服务哪家好
我的世界综合服务器手游
游戏软件开发专业代码
按照网络安全等级保护制度
做软件开发还是项目管理