链表作为最基础的数据结构,在许多高级语言上已经有了很好的实现。由于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. Redis命令拾遗五(有序集合)

    本文版权归博客园和作者吴双本人共同所有,博客园蜗牛NoSql系列分享 http://www.cnblogs.com/tdws/tag/NoSql/ Sorted Set 有序集合—Sorted Set ...

  2. JavaScript jQuery 中定义数组与操作及jquery数组操作

    首先给大家介绍javascript jquery中定义数组与操作的相关知识,具体内容如下所示: 1.认识数组 数组就是某类数据的集合,数据类型可以是整型.字符串.甚至是对象Javascript不支持多 ...

  3. C#开发微信门户及应用(8)-微信门户应用管理系统功能介绍

    最近对微信接口进行深入的研究,通过把底层接口一步步进行封装后,逐步升级到自动化配置.自动化应答,以及后台处理界面的优化和完善上,力求搭建一个较为完善.适用的微信门户应用管理系统. 微信门户应用管理系统 ...

  4. Mac入门(三)使用brew安装软件

    brew 又叫Homebrew,是Mac OSX上的软件包管理工具,能在Mac中方便的安装软件或者卸载软件, 只需要一个命令, 非常方便 brew类似ubuntu系统下的apt-get的功能 阅读目录 ...

  5. Maven部署构件至远程仓库

    私服的一大作用就是部署第三方构件,包括组织内的生成的构件以及一些无法从外部仓库获取的构件.无论是日常开发中生成的构件,还是正式版本发布的构件,都需要部署到仓库中,供其它团队成员使用.Maven除了能对 ...

  6. jQuery orbit 幻灯片

    在线实例 默认 带缩略图 带描述 使用方法 <div class="wrap" style="width: 565px; height: 290px; margin ...

  7. 写给自己:修改配置文件一定要cp一个.bak

    写给自己:修改配置文件一定要cp一个.bak 毕竟不是每次的修改都一定对,而且很多时候是在服务器上直接修改原文件,修改后重启服务才知道是否修改正确,如果不加备份修改,造成服务器动荡,将会造成不可挽回的 ...

  8. MAC的SVN怎么设置允许.a文件上传

    首先在mac中svn的安装会去选择Cornerstone 如果遇到这个问题肯定是已经安装并准备上传.a 文件了.首先要清楚svn是默认过滤忽略.a文件的上传的,要想可以上传.a 可以通过这个简单的方法 ...

  9. iOS---关于UIWebView

    1.加载的web界面可以自由收缩 webView.scalesPageToFit = YES;

  10. UILabel 自适应宽高

    #import <UIKit/UIKit.h> @interface UILabel (UILabel_LabelHeighAndWidth) + (CGFloat)getHeightBy ...