redis源码分析(3)-- 基本数据结构双链表list

一、双链表结构

redis中实现的双链表结构体如下:

1 typedef struct list {
2     listNode *head; # 链表头
3     listNode *tail; # 链表尾
4     void *(*dup)(void *ptr); # 复制链表函数
5     void (*free)(void *ptr); # 释放节点函数
6     int (*match)(void *ptr, void *key); # 匹配函数
7     unsigned long len; # 链表节点个数
8 } list;

包含三个节点的list组成如图:

每个listNode的结构:

1 typedef struct listNode {
2     struct listNode *prev;
3     struct listNode *next;
4     void *value;
5 } listNode;

Redis链表list特点:

1、双端:每个节点包括前向指针prev和后级指针next,获取节点前后节点都是O(1)

2、无环:首节点prev=NULL,尾节点next=NULL

3、list结构包含表头指针和表尾指针,获取头尾节点时间复杂度O(1)

4、list包含节点计数器len,获取节点长度只需要O(1)

5、多态; 节点value为void*, 并且可以通过函数指针dup、free、match为节点设置属性。

 

二、list迭代器

链表其他操作比较简单,这里主要介绍list中的迭代器使用。先看下迭代器在遍历链表中的应用

 1 listNode *listSearchKey(list *list, void *key)
 2 {
 3     listIter *iter;
 4     listNode *node;
 5 
 6     iter = listGetIterator(list, AL_START_HEAD); # 获取从头开始的迭代器
 7     while((node = listNext(iter)) != NULL) { # 从迭代器依次获取下个节点,并开始遍历
 8         if (list->match) {
 9             if (list->match(node->value, key)) {
10                 listReleaseIterator(iter);
11                 return node;
12             }
13         } else {
14             if (key == node->value) {
15                 listReleaseIterator(iter);
16                 return node;
17             }
18         }
19     }
20     listReleaseIterator(iter); # 释放迭代器
21     return NULL;
22 }

 获取迭代器源码:

 1 listIter *listGetIterator(list *list, int direction)
 2 {
 3     listIter *iter;
 4 
 5     if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
 6     if (direction == AL_START_HEAD) # 根据direction,得到链表头或者链表尾节点
 7         iter->next = list->head;
 8     else
 9         iter->next = list->tail;
10     iter->direction = direction;
11     return iter;
12 }

迭代器结构:

1 typedef struct listIter {
2     listNode *next;
3     int direction;
4 } listIter;

三、链表操作

 

posted on 2017-07-22 23:55  ym65536  阅读(442)  评论(0编辑  收藏  举报