链表的作用
首先我们知道,链表提供了高效的节点重排能力、顺序性的访问方式、灵活的增删节点并调整链表的长度。作为一种常用的数据结构,在很多高级的编程语言里都可以看到。实现的方式大同小异。
与数组的比较
从内存空间来看,数组是一个连续的内存空间属于连续存储存储形式。而链表则是离散存储的存储形式,有一个指针指向一个节点。所以意味着链表在内存中可以是离散的。
就从内存存储方式来看,数组是一个连续的空间,查询更快,更加适合使用序列来访问数组元素。而链表更适对线性表长度无法确定,频繁的插入删除操作的动态性比较强的线性表。下图可见,数组和链表的存储形式。
数组 | 链表 |
---|---|
a | other |
b | a |
c | other |
d | b |
e | other |
nil | c |
节点的定义
首先我们看一下节点的定义。
prev 记录前一个节点的指针
next 记录下一个节点的指针
value 记录节点的阵阵的值
这样如果你知道第一个节点就能完整的把整个链表循环显示出来。
其实目前来看整个链表的结构已经出现了,多个listNode通过prev next 就可以连起来行程一个链表。但是redis中的链表还对listNode 进行了一个封装,增加了一些冗余字段来提高访问的性能,跟上一篇文章说的SDS有相似地方。
typedef struct listNode{
//前置节点
struct listNode *prev;
//后置节点
struct listNode *next;
//节点的值
void *value;
}
Redis中的list
在redis中对listNode再次封装了下,使用了一个list。下面我们看下代码:
可以看到跟SDS类似,多了一个表头,表尾,数量和3个函数。
这几个属性能够达到什么效果呢?
这3个函数可以说是对链表最常用的函数,使用起来十分的方便。链表数量作用跟SDS相似,可以用O(1)的复杂度获取整个链表的长度,表头和表尾可以快速的在表头和表尾添加元素。否则如果要在最后添加需要循环整个链表拿到尾节点,改变尾节点的next添加新节点。在redis中使用链表,几乎都是使用list。
typedef struct list{
//链表头
listNode *head;
//链表尾
listNode *tail;
//链表数量
unsigned long len;
//节点复制韩式布
vode *(*dup) (void *ptr);
//节点释放
vode *(*free) (void *ptr);
//节点对比
vode *(*match) (void *ptr,void *key);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。