您的位置:首页 > 理论基础 > 数据结构算法

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

2017-07-22 23:55 603 查看
一、双链表结构

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;


三、链表操作



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: