/Redis/0.4.md
https://github.com/AI-algorithms/project-readme · Markdown · 269 lines · 216 code · 53 blank · 0 comment · 0 complexity · 04129abd02e1bf17f794d0eb818b63e9 MD5 · raw file
- #### Redis源码分析-List
-
- > 由于之前看注释版本的源码,所以此分析也是基于Redis2.6版本,之后会分析最新5.x源码
- # 定义
- 链表节点结构
- ```markdown
- typedef struct listNode {
- // 前驱节点
- struct listNode *prev;
- // 后继节点
- struct listNode *next;
- // 值
- void *value;
- } listNode;
- ```
- 链表结构
- ```markdown
- typedef struct list {
- // 表头指针,直接定位
- listNode *head;
- // 表尾指针,直接定位
- listNode *tail;
- // 节点数量,直接获得
- unsigned long len;
- // 复制函数
- void *(*dup)(void *ptr);
- // 释放函数
- void (*free)(void *ptr);
- // 比对函数
- int (*match)(void *ptr, void *key);
- } list;
- ```
- # 使用
- - `llen`命令返回list长度,直接返回的是链表的len属性
- - list可以左进右出(或者右进左出)实现FIFO队列;抑或是左进左出(或者右进右出)实现stack,且push和pop操作函数都是O(1)的
- - list的node,带前驱和后继指针,组成双端链表
- # Redis LIST API
- 创建链表
- ```markdown
- 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;
- }
- ```
- 新建一个包含给定 value 的节点,并将它加入到列表的表头
- ```markdown
- 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长度+1
- list->len++;
- return list;
- }
- ```
- 释放整个列表(以及列表包含的节点)
- ```markdown
- void listRelease(list *list) {
- unsigned long len;
- listNode *current, *next;
- //从链表头开始挨个往后遍历,挨个释放每个node
- current = list->head;
- //根据链表长度,释放len次
- len = list->len;
- while(len--) {
- next = current->next;
- // 如果列表有自带的 free 方法,那么先对节点值调用它
- if (list->free) list->free(current->value);
- // 之后再释放节点
- zfree(current);
- current = next;
- }
- zfree(list);
- }
- ```
- 新建一个包含给定 value 的节点,并将它加入到列表的表尾
- ```markdown
- 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;
- }
- ```
- 创建一个包含值 value 的节点,并根据 after 参数的指示,将新节点插入到 old_node 的之前或者之后
- ```markdown
- 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) {
- // 插入到 old_node 之后
- node->prev = old_node;
- node->next = old_node->next;
- // 处理表尾节点
- if (list->tail == old_node) {
- list->tail = node;
- }
- } else {
- // 插入到 old_node 之前
- 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;
- }
- ```
- 释放列表中给定的节点
- ```markdown
- 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--;
- }
- ```
- 在列表中查找和 key 匹配的节点
- ```markdown
- 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 {
- // 直接用列表的值来比对
- if (key == node->value) {
- listReleaseIterator(iter);
- return node;
- }
- }
- }
- // 没找到
- listReleaseIterator(iter);
- return NULL;
- }
- ```
- 根据给定索引,返回列表中对应的节点
- ```markdown
- listNode *listIndex(list *list, long index) {
- listNode *n;
- if (index < 0) {
- index = (-index)-1;
- n = list->tail;
- while(index-- && n) n = n->prev;
- } else {
- n = list->head;
- while(index-- && n) n = n->next;
- }
- return n;
- }
- ```