链表作为最基础的数据结构,在许多高级语言上已经有了很好的实现。由于redis采用C语言编写,需要自己实现链表,于是redis在adlist.h定义了链表类型。作者对于这部分没什么好说,源码比较简单,如果这方面没有接触过的话,作者也耐心地推荐了几本书供参考。为了提高效率,这里的链表指的是双向链表,使得某一个元素访问它的前驱与后继的时间复杂度均为O(1)。

  

  不多说,进入正题,首先可以看到节点的数据结构的代码如下:

typedef struct listNode {
struct listNode *prev; //前驱节点
struct listNode *next; //后继节点
void *value; //值
} listNode;

  C语言没有泛型,但是链表又要存储各种类型的数据,所以这里使用了void指针。由于指针只在编译器级别进行检查,在指令级别是没有类型的,所以这里是OK的。这里的value*指向真正的值存储空间。

  按理说使用上面的结构已经可以实现一个简单的链表,redis为了更加简便的使用链表,使用list结构体对节点进行了封装。

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;

  使用C语言实现面向对象编程的关键是定义函数指针作为接口,在使用时进行实现,这里定义了三种方法指针,分别用于类型的拷贝(在链表拷贝时调用),类型的释放(在链表释放时调用),类型的比较(类似于C++的运算符重载,用于比较类似的大小),这里的链表定义的写法值得好好学习一下。

   使用以上结构,redis存储一个简单的链表示意图如下:

  这里可以看到,redis实现的是无环链表,因为首元素的前驱是NULL。这样设计的理由是list已经持有了首元素和尾元素的指针,无需另外在首尾之间组成回路。这张图已经很明显的展示了链表的工作状态,下面对链表的操作的讨论仅以链表插入为例子来进行分析:

list *listAddNodeTail(list *list, void *value)
{
listNode *node; //定义保存值的节点 if ((node = zmalloc(sizeof(*node))) == NULL) //为这个新的节点进行分配空间
return NULL;
node->value = value;
if (list->len == ) { //链表为空的时候
list->head = list->tail = node;
node->prev = node->next = NULL;
} else {
node->prev = list->tail;
node->next = NULL;
list->tail->next = node;
list->tail = node;
}
list->len++;
return list;
}

  进行插入的过程比较容易,先定义出节点元素,然后根据链表的当前节点数进行不同的操作:当链表为空时,将list对应域指向node,而当链表不为空时,先完成新节点的成员赋值,然后再更改list的tail域等等,这里一定要注意的是双向列表的节点改变,要留心prev与next的值是否改变,而且新旧节点改变的顺序一定不能错,这个虽然简单,但是还是比较考验基本功的。

  总结:可以看出,一些知名的软件,底层还是最基础的东西,并没有什么黑科技,所以掌握好基础真的很重要。作者对这一章描述的比较简单,也就没什么好讲的了。希望以后可以继续坚持写博客。

Redis设计与实现读书笔记(二) 链表的更多相关文章

  1. Redis设计与实现读书笔记——双链表

    前言 首先,贴一下参考链接: http://www.redisbook.com/en/latest/internal-datastruct/adlist.html, 另外真赞文章的作者,一个90后的小 ...

  2. Redis设计与实现读书笔记——简单动态字符串

    前言 项目里用到了redis数据结构,不想只是简单的调用api,这里对我的读书笔记做一下记录.原文地址: http://www.redisbook.com/en/latest/internal-dat ...

  3. Redis设计与实现读书笔记(一) SDS

    作为redis最基础的底层数据结构之一,SDS提供了许多C风格字符串所不具备的功能,为之后redis内存管理提供了许多方便.它们分别是: 二进制安全 减少字符串长度获取时间复杂度 杜绝字符串溢出 减少 ...

  4. Redis 设计与实现读书笔记一 Redis字符串

    1 Redis 是C语言实现的 2 C字符串是 /0 结束的字符数组 3 Redis具体的动态字符串实现 /* * 保存字符串对象的结构 */ struct sdshdr { // buf 中已占用空 ...

  5. <<redis设计和实现>>读书笔记

    redis如何实现主从同步的高效率?? 主从复制的同步有一个命令数据的同步文本,然后利用两个不同服务器的偏移量来进行进行同步,避免每次都是全部同步(并非会保存所有的命令数据,而是会有一个缓冲区(比如1 ...

  6. Redis 设计与实现读书笔记一 Redis List

    list结构体 adlist.h/list(源码位置) /* * 双端链表结构 */ typedef struct list { // 表头节点 listNode *head; // 表尾节点 lis ...

  7. Linux内核设计与实现 读书笔记 转

    Linux内核设计与实现  读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://bl ...

  8. 【2018.08.13 C与C++基础】C++语言的设计与演化读书笔记

    先占坑 老实说看这本书的时候,有很多地方都很迷糊,但却说不清楚问题到底在哪里,只能和Effective C++联系起来,更深层次的东西就想不到了. 链接: https://blog.csdn.net/ ...

  9. 《你必须知道的.NET》读书笔记二:小OO有大原则

    此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.单一职责原则 (1)核心思想:一个类最好只做一件事,只有一个引起它变化的原因 (2)常用模式:Fa ...

随机推荐

  1. java访问修饰符

    了解面向对象思想的同学们,都知道"封装"这一基本特征,如何正确运用访问修饰符,恰恰能体现出封装的好坏. java访问修饰符有四个: 1)public:访问权限最高,其修饰的类.类变 ...

  2. FFmpeg滤镜实现区域视频增强 及 D3D实现视频播放区的拉大缩小

    1.区域视频增强 FFmpeg滤镜功能十分强大,用滤镜可以实现视频的区域增强功能. 用eq滤镜就可以实现亮度.对比度.饱和度等的常用视频增强功能. 推荐两篇写得不错的博文: (1)ffmpeg综合应用 ...

  3. java 开发业务逻辑的思考(1)- 通知短信发送

    坚持每天写一个总结的博客,今天又是一个新的开始! 今天我要说的是一个关于发送短信通知发送的问题.具体的业务流程是这样的,现在需要对用户的一个提现的申请进行审核,审核的内部需要控制很多的业务, 1.检查 ...

  4. elasticsearch高级配置一 ---- 分片分布规则设置

    cluster.routing.allocation.allow_rebalance 设置根据集群中机器的状态来重新分配分片,可以设置为always, indices_primaries_active ...

  5. jsPanel插件Option总结

    jsPanel插件Option总结 学习jsPanel之余对相关的选项进行了总结,便于参考. # 选项名称 类别 简要说明 1 autoclose configuration 设置一个时间在毫秒后,面 ...

  6. 浅谈Hybrid技术的设计与实现第二弹

    前言 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 浅谈Hybrid技术的设计与实现第三弹——落地篇 接上文:浅谈Hybrid技术的设计与实现(阅读本文前,建议阅读这个先) ...

  7. 超小Web手势库AlloyFinger原理

    目前AlloyFinger作为腾讯手机QQ web手势解决方案,在各大项目中都发挥着作用. 感兴趣的同学可以去Github看看:https://github.com/AlloyTeam/AlloyFi ...

  8. 事件分发时候的onTouchEvent,onInterceptTouchEvent,dispatchTouchEvent调用顺序

    一直想弄清楚onTouchEvent,onInterceptTouchEvent,dispatchTouchEvent的执行顺序,以及内部使用switch (event.getAction())中的执 ...

  9. 软件海贼团 OnePiece (版权所有)

    最近迷上了“海贼王”这部动画片,不仅仅是因为其中的人物个个性格鲜明,剧情跌宕起伏扣人心弦,各种耍宝搞笑,还感觉到这个团队很像理想中的敏捷软件团队. 作为一直带团队的我,感觉“海贼王”这个动画片给了我很 ...

  10. C#冒泡排序算法

    用了两种形式的数据,一个是泛型List,一个是数据int[].记录一下,作为自己学习过程中的笔记. using System; using System.Collections.Generic; us ...