Redis内部数据结构详解之双向链表(linkedlist)
2013-12-21 15:52
501 查看
本文所引用的源码全部来自Redis2.8.2版本。
Redis中linkedlist数据结构与API相关文件是adlist.c, adlist.h。
本文主要讲解Redis中对双向链表的详细实现,以及相关API的分析,对于双向链表本身可以从任意一本数据结构书本中得到详解。
转载请注明,来自:http://blog.csdn.net/acceptedxukai/article/details/17467373
listNode拥有prev前驱指针和next后继指针,因此通过迭代器可以很方便的对链表从从头至尾或从尾至头遍历;
list拥有header头指针和tail为指针,对于在链表的头部或尾部进行插入节点的时间复杂度全部为O(1),高效地实现了Redis中一些指令的操作;
list自带保存链表长度的字段len,使得计算链表长度的时间复杂度为O(1)。
双向链表实现简单,Redis对双向链表加以改造,添加保存节点长度的字段,以及实现自己的迭代指针,使得一些数据操作变得简单。
最后感谢黄健宏(huangz1990)的Redis设计与实现及其他对Redis2.6源码的相关注释对我在研究Redis2.8源码方面的帮助。
Redis中linkedlist数据结构与API相关文件是adlist.c, adlist.h。
本文主要讲解Redis中对双向链表的详细实现,以及相关API的分析,对于双向链表本身可以从任意一本数据结构书本中得到详解。
转载请注明,来自:http://blog.csdn.net/acceptedxukai/article/details/17467373
一、双向链表简介
双向链表作为一种常见的数据结构,在严蔚敏数据结构书里有详细的讲解,双向链表的每个数据节点都有两个指针,分别指向后继与前驱节点,因此从双向链表中的任意一个节点开始都可以很方便地访问其前驱与后继节点。二、Redis中双向链表数据结构以及相关宏定义
typedef struct listNode { struct listNode *prev;//前驱指针 struct listNode *next;//后继指针 void *value; //节点的值 } listNode; typedef struct listIter {//链表迭代器 listNode *next; int direction;//遍历方向 } listIter; typedef struct list {//链表 listNode *head;//链表头 listNode *tail;//链表尾 void *(*dup)(void *ptr); //复制函数指针 void (*free)(void *ptr); //释放内存函数指针 int (*match)(void *ptr, void *key); //比较函数指针 unsigned long len; //链表长度 } list;
宏名称 | 作用 |
listLength | 获取链表的长度值 |
listFirst | 获取链表的首指针 |
listLast | 获取链表的尾指针 |
listPrevNode | 获取当前节点的前驱节点指针 |
listNextNode | 获取当前节点的后继节点指针 |
listNodeValue | 获取当前节点所存储的值 |
listSetDupMethod | 设置链表节点value的复制函数 |
listSetFreeMethod | 设置链表节点value的释放内存函数 |
listSetMatchMethod | 设置链表节点value的比较函数 |
listGetDupMethod | 获取链表节点value的复制函数 |
listGetFree | 获取链表节点value的释放内存函数 |
listGetMatchMethod | 获取链表节点value的比较函数 |
三、Redis中双向链表API介绍
名称 | 作用 | 复杂度 |
listCreate | 创建一个新双向链表 | O(1) |
listRelease | 释放一个双向链表以及包含的节点内存 | O(N) |
listAddNodeHead | 将一个节点添加到链表的表头 | O(1) |
listAddNodeTail | 将一个节点添加到链表的表尾 | O(1) |
listInsertNode | 将一个节点添加到给定节点的之后或之前 | O(1) |
listDelNode | 删除给定的节点 | O(1) |
listGetIterator | 生成双向链表的迭代器 | O(1) |
listReleaseIterator | 释放双向链表的迭代器 | O(1) |
listNext | 通过迭代器获取下一个节点 | O(1) |
listDup | 创建给定链表的副本 | O(N) |
listSearchKey | 查找与给定key相同值的节点 | O(N) |
listIndex | 根据给定的索引值,返回相应的节点 | O(N) |
listRewind | 重新初始化迭代器,迭代方向从头至尾 | O(1) |
listRewindTail | 重新初始化迭代器,迭代方向从尾至头 | O(1) |
listRotate | 取出链表尾节点并插入到头部 | O(1) |
四、Redis双向链表性能分析
Redis中的双向链表也许是Redis中最简单最容易实现的数据结构,对于API就不多说了,都很简单,也没啥可以说的,下面简单分析一下双向链表的性能。listNode拥有prev前驱指针和next后继指针,因此通过迭代器可以很方便的对链表从从头至尾或从尾至头遍历;
list拥有header头指针和tail为指针,对于在链表的头部或尾部进行插入节点的时间复杂度全部为O(1),高效地实现了Redis中一些指令的操作;
list自带保存链表长度的字段len,使得计算链表长度的时间复杂度为O(1)。
五、小结
双向链表主要有两个作用:作为Redis列表数据类型的底层实现方法之一;作为通用数据结构可以被其他功能模块使用。双向链表实现简单,Redis对双向链表加以改造,添加保存节点长度的字段,以及实现自己的迭代指针,使得一些数据操作变得简单。
最后感谢黄健宏(huangz1990)的Redis设计与实现及其他对Redis2.6源码的相关注释对我在研究Redis2.8源码方面的帮助。
相关文章推荐
- redis安装问题小结
- Redis偶发连接失败案例实战记录
- redis中修改配置文件中的端口号 密码方法
- 利用yum安装Redis的方法详解
- 为啥懒 Redis 是更好的 Redis
- 详解Redis使用认证密码登录
- Redis 在真实世界的 5 个用法
- Redis中的动态字符串学习教程
- 详解Redis开启远程登录连接
- redis实现加锁的几种方法示例详解
- Redis 集群搭建和简单使用教程
- redis 队列操作的例子(php)
- Redis中五种数据类型简单操作
- redis启动流程介绍
- redis安装和配置_动力节点Java学院整理
- Linux安装单机版Redis的完整步骤
- 浅谈redis在项目中的应用
- php中使用redis队列操作实例代码
- redis的主从配置方法详解
- 在PHP中使用redis