ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 概述 Redis中的List是一个有序(按加入的时序排序)的数据结构,一般有序我们会采用数组或者是双向链表,其中双向链表由于有前后指针实际上会很浪费内存。3.2版本之前采用两种数据结构作为底层实现: * 压缩列表ziplist * 双向链表linkedlist 在知道了`ziplist`原理后,我们来看一下在*压缩列表转化成双向链表的条件*: * 如果添加的字符串元素长度超过默认值64 * zip包含的节点数超过默认值512 这两个条件是可以修改的,在`redis.conf`中 ``` list-max-ziplist-value 64 list-max-ziplist-entries 512   ``` ## list数据结构 adlist.h ``` //node的结点 typedef struct listNode { struct listNode *prev; //结点的前一结点 struct listNode *next; //结点的下一结点 void *value; //node的函数指针 } listNode; //list迭代器,只能为单向 typedef struct listIter { listNode *next; //当前迭代位置的下一点 int direction; //方向 } listIter; //node的list列表 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; /* Functions implemented as macros */ #define listLength(l) ((l)->len) //获取list长度 #define listFirst(l) ((l)->head) //获取list头 #define listLast(l) ((l)->tail) //获取list尾 #define listPrevNode(n) ((n)->prev) //获取给定结点的上一个结点 #define listNextNode(n) ((n)->next) //获取给定结点的下一个结点 #define listNodeValue(n) ((n)->value) //获取给定结点的值,这个value不是一个数值类型,而是一个函数指针 #define listSetDupMethod(l,m) ((l)->dup = (m))//复制函数方法设置 #define listSetFreeMethod(l,m) ((l)->free = (m))//释放函数方法设置 #define listSetMatchMethod(l,m) ((l)->match = (m))//匹配函数方法设置 #define listGetDupMethod(l) ((l)->dup)//获取复制函数指针 #define listGetFreeMethod(l) ((l)->free)//获取释放函数指针 #define listGetMatchMethod(l) ((l)->match)//匹配函数指针 ``` C++通过class来面向对象编程,从上面可以看出C语言是通过在struct中对象的构造、复制、还有释放是通过函数指针来实现模块化的。这就是两者的区别。 这是一个双向链表实现。 ## 创建 & 迭代 & 销毁 创建 ``` list *listCreate(void); ``` 添加到链表头部或尾部 ``` list *listAddNodeHead(list *list, void *value); list *listAddNodeTail(list *list, void *value); ``` 销毁 ``` void listRelease(list *list); void listEmpty(list *list); ```