/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

  1. #### Redis源码分析-List
  2. > 由于之前看注释版本的源码所以此分析也是基于Redis2.6版本之后会分析最新5.x源码
  3. # 定义
  4. 链表节点结构
  5. ```markdown
  6. typedef struct listNode {
  7. // 前驱节点
  8. struct listNode *prev;
  9. // 后继节点
  10. struct listNode *next;
  11. // 值
  12. void *value;
  13. } listNode;
  14. ```
  15. 链表结构
  16. ```markdown
  17. typedef struct list {
  18. // 表头指针,直接定位
  19. listNode *head;
  20. // 表尾指针,直接定位
  21. listNode *tail;
  22. // 节点数量,直接获得
  23. unsigned long len;
  24. // 复制函数
  25. void *(*dup)(void *ptr);
  26. // 释放函数
  27. void (*free)(void *ptr);
  28. // 比对函数
  29. int (*match)(void *ptr, void *key);
  30. } list;
  31. ```
  32. # 使用
  33. - `llen`命令返回list长度直接返回的是链表的len属性
  34. - list可以左进右出或者右进左出实现FIFO队列抑或是左进左出或者右进右出实现stack且push和pop操作函数都是O(1)
  35. - list的node带前驱和后继指针组成双端链表
  36. # Redis LIST API
  37. 创建链表
  38. ```markdown
  39. list *listCreate(void) {
  40. struct list *list;
  41. // 为列表结构分配内存
  42. if ((list = zmalloc(sizeof(*list))) == NULL)
  43. return NULL;
  44. // 初始化属性
  45. list->head = list->tail = NULL;
  46. list->len = 0;
  47. list->dup = NULL;
  48. list->free = NULL;
  49. list->match = NULL;
  50. return list;
  51. }
  52. ```
  53. 新建一个包含给定 value 的节点并将它加入到列表的表头
  54. ```markdown
  55. list *listAddNodeHead(list *list, void *value) {
  56. listNode *node;
  57. if ((node = zmalloc(sizeof(*node))) == NULL)
  58. return NULL;
  59. node->value = value;
  60. if (list->len == 0) {
  61. // 第一个节点
  62. list->head = list->tail = node;
  63. node->prev = node->next = NULL;
  64. } else {
  65. // 不是第一个节点
  66. node->prev = NULL;
  67. node->next = list->head;
  68. list->head->prev = node;
  69. list->head = node;
  70. }
  71. //list长度+1
  72. list->len++;
  73. return list;
  74. }
  75. ```
  76. 释放整个列表(以及列表包含的节点)
  77. ```markdown
  78. void listRelease(list *list) {
  79. unsigned long len;
  80. listNode *current, *next;
  81. //从链表头开始挨个往后遍历,挨个释放每个node
  82. current = list->head;
  83. //根据链表长度,释放len次
  84. len = list->len;
  85. while(len--) {
  86. next = current->next;
  87. // 如果列表有自带的 free 方法,那么先对节点值调用它
  88. if (list->free) list->free(current->value);
  89. // 之后再释放节点
  90. zfree(current);
  91. current = next;
  92. }
  93. zfree(list);
  94. }
  95. ```
  96. 新建一个包含给定 value 的节点并将它加入到列表的表尾
  97. ```markdown
  98. list *listAddNodeTail(list *list, void *value) {
  99. listNode *node;
  100. if ((node = zmalloc(sizeof(*node))) == NULL)
  101. return NULL;
  102. node->value = value;
  103. if (list->len == 0) {
  104. // 第一个节点
  105. list->head = list->tail = node;
  106. node->prev = node->next = NULL;
  107. } else {
  108. // 不是第一个节点
  109. node->prev = list->tail;
  110. node->next = NULL;
  111. list->tail->next = node;
  112. list->tail = node;
  113. }
  114. list->len++;
  115. return list;
  116. }
  117. ```
  118. 创建一个包含值 value 的节点并根据 after 参数的指示将新节点插入到 old_node 的之前或者之后
  119. ```markdown
  120. list *listInsertNode(list *list, listNode *old_node, void *value, int after) {
  121. listNode *node;
  122. if ((node = zmalloc(sizeof(*node))) == NULL)
  123. return NULL;
  124. node->value = value;
  125. if (after) {
  126. // 插入到 old_node 之后
  127. node->prev = old_node;
  128. node->next = old_node->next;
  129. // 处理表尾节点
  130. if (list->tail == old_node) {
  131. list->tail = node;
  132. }
  133. } else {
  134. // 插入到 old_node 之前
  135. node->next = old_node;
  136. node->prev = old_node->prev;
  137. // 处理表头节点
  138. if (list->head == old_node) {
  139. list->head = node;
  140. }
  141. }
  142. // 更新前置节点和后继节点的指针
  143. if (node->prev != NULL) {
  144. node->prev->next = node;
  145. }
  146. if (node->next != NULL) {
  147. node->next->prev = node;
  148. }
  149. // 更新列表节点数量
  150. list->len++;
  151. return list;
  152. }
  153. ```
  154. 释放列表中给定的节点
  155. ```markdown
  156. void listDelNode(list *list, listNode *node) {
  157. // 处理前驱节点的指针
  158. if (node->prev)
  159. node->prev->next = node->next;
  160. else
  161. list->head = node->next;
  162. // 处理后继节点的指针
  163. if (node->next)
  164. node->next->prev = node->prev;
  165. else
  166. list->tail = node->prev;
  167. // 释放节点值
  168. if (list->free) list->free(node->value);
  169. // 释放节点
  170. zfree(node);
  171. // 更新列表节点数量
  172. list->len--;
  173. }
  174. ```
  175. 在列表中查找和 key 匹配的节点
  176. ```markdown
  177. listNode *listSearchKey(list *list, void *key) {
  178. listIter *iter;
  179. listNode *node;
  180. // 使用迭代器查找
  181. iter = listGetIterator(list, AL_START_HEAD);
  182. while((node = listNext(iter)) != NULL) {
  183. if (list->match) {
  184. // 使用列表自带的匹配器进行比对
  185. if (list->match(node->value, key)) {
  186. listReleaseIterator(iter);
  187. return node;
  188. }
  189. } else {
  190. // 直接用列表的值来比对
  191. if (key == node->value) {
  192. listReleaseIterator(iter);
  193. return node;
  194. }
  195. }
  196. }
  197. // 没找到
  198. listReleaseIterator(iter);
  199. return NULL;
  200. }
  201. ```
  202. 根据给定索引返回列表中对应的节点
  203. ```markdown
  204. listNode *listIndex(list *list, long index) {
  205. listNode *n;
  206. if (index < 0) {
  207. index = (-index)-1;
  208. n = list->tail;
  209. while(index-- && n) n = n->prev;
  210. } else {
  211. n = list->head;
  212. while(index-- && n) n = n->next;
  213. }
  214. return n;
  215. }
  216. ```