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;

三、链表操作

时间: 2024-12-30 03:54:53

redis源码分析(3)-- 基本数据结构双链表list的相关文章

redis源码分析4---结构体---跳跃表

redis源码分析4---结构体---跳跃表 跳跃表是一种有序的数据结构,他通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的: 跳跃表支持平均O(logN),最坏O(N)复杂度的节点查找,还可以通过顺序性操作来批量处理节点.性能上和平衡树媲美,因为事先简单,常用来代替平衡树. 在redis中,只在两个地方使用了跳跃表,一个是实现有序集合键,另一个是在集群节点中用作内部数据结构. 1 跳跃表节点 1.1 层 层的数量越多,访问其他节点的速度越快: 1.2 前进指针 遍历举例

redis源码分析3---结构体---字典

redis源码分析3---结构体---字典 字典,简单来说就是一种用于保存键值对的抽象数据结构: 注意,字典中每个键都是独一无二的:在redis中,内部的redis的数据库就是使用字典作为底层实现的: 1 字典的实现 在redis中,字典是使用哈希表作为底层实现的,一个hash表里面可以有多个hash表节点,而每个hash表节点就保存了字典中的一个键值对: hash表定义 table属性是一个数组,数组中的每个元素都是一个指向dictEntry结构的指针,每个dictEntry结构保存着一个键值

redis 源码分析(一) 内存管理

一,redis内存管理介绍 redis是一个基于内存的key-value的数据库,其内存管理是非常重要的,为了屏蔽不同平台之间的差异,以及统计内存占用量等,redis对内存分配函数进行了一层封装,程序中统一使用zmalloc,zfree一系列函数,其对应的源码在src/zmalloc.h和src/zmalloc.c两个文件中,源码点这里. 二,redis内存管理源码分析 redis封装是为了屏蔽底层平台的差异,同时方便自己实现相关的函数,我们可以通过src/zmalloc.h 文件中的相关宏定义

redis源码分析之事务Transaction(下)

接着上一篇,这篇文章分析一下redis事务操作中multi,exec,discard三个核心命令. 原文地址:http://www.jianshu.com/p/e22615586595 看本篇文章前需要先对上面文章有所了解: redis源码分析之事务Transaction(上) 一.redis事务核心命令简介 redis事务操作核心命令: //用于开启事务 {"multi",multiCommand,1,"sF",0,NULL,0,0,0,0,0}, //用来执行事

redis源码分析之内存布局

redis源码分析之内存布局 1. 介绍 众所周知,redis是一个开源.短小.高效的key-value存储系统,相对于memcached,redis能够支持更加丰富的数据结构,包括: 字符串(string) 哈希表(map) 列表(list) 集合(set) 有序集(zset) 主流的key-value存储系统,都是在系统内部维护一个hash表,因为对hash表的操作时间复杂度为O(1).如果数据增加以后,导致冲突严重,时间复杂度增加,则可以对hash表进行rehash,以此来保证操作的常量时

redis源码解析之dict数据结构

dict 是redis中最重要的数据结构,存放结构体redisDb中. typedef struct dict { dictType *type; void *privdata; dictht ht[2]; int rehashidx; /* rehashing not in progress if rehashidx == -1 */ int iterators; /* number of iterators currently running */ } dict; 其中type是特定结构的处

redis源码分析(1)--makefile和目录结构分析

一.redis源码编译 redis可以直接在官网下载(本文使用版本 3.0.7):https://redis.io/download 安装: $ tar xzf redis-3.0.7.tar.gz $ cd redis-3.0.7 $ make make执行以后主要编译产物在src/redis-server src/redis-cli 如果想把redis-server直接install到可执行目录/usr/local/bin,还需要执行: $ make install Run Redis wi

redis源码分析之事务Transaction(上)

这周学习了一下redis事务功能的实现原理,本来是想用一篇文章进行总结的,写完以后发现这块内容比较多,而且多个命令之间又互相依赖,放在一篇文章里一方面篇幅会比较大,另一方面文章组织结构会比较乱,不容易阅读.因此把事务这个模块整理成上下两篇文章进行总结. 原文地址:http://www.jianshu.com/p/acb97d620ad7 这篇文章我们重点分析一下redis事务命令中的两个辅助命令:watch跟unwatch. 一.redis事务辅助命令简介 依然从server.c文件的命令表中找

Redis源码分析(一)--Redis结构解析

从今天起,本人将会展开对Redis源码的学习,Redis的代码规模比较小,非常适合学习,是一份非常不错的学习资料,数了一下大概100个文件左右的样子,用的是C语言写的.希望最终能把他啃完吧,C语言好久不用,快忘光了.分析源码的第一步,先别急着想着从哪开始看起,先浏览一下源码结构,可以模块式的渐入,不过比较坑爹的是,Redis的源码全部放在在里面的src目录里,一下90多个文件统统在里面了,所以我选择了拆分,按功能拆分,有些文件你看名字就知道那是干什么的.我拆分好后的而结果如下: 11个包,这样每

Redis源码分析(四)-- sds字符串

今天分析的是Redis源码中的字符串操作类的代码实现.有了上几次的分析经验,渐渐觉得我得换一种分析的方法,如果每个API都进行代码分析,有些功能性的重复,导致分析效率的偏低.所以下面我觉得对于代码的分析偏重的是一种功能整体的思维实现来讲解,其中我也会挑出一个比较有特点的方法进行拆分了解,这也可以让我们见识一下里面的一些神奇的代码.好,回归正题,说到字符串,这不管放到哪个编程语言中,都是使用频率极高的操作类.什么new String, concat, strcopy,substr, splitSt