redis学习笔记(2)---链表adlist
2016-05-03 20:03
477 查看
adlist
redis通过prev、next指针实现了双向链表adlist,并通过void*指向数据,用来实现泛型。与list相关的命令主要有:LPOP,LPUSH,RPOP,RPUSH,LLEN
定义
typedef struct listNode { //链表节点 struct listNode *prev; struct listNode *next; void *value; } listNode; 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;
list通过head、tail分别保存了链表的头节点和尾部节点,这样LPOP,LPUSH,RPOP,RPUSH这几个操作的时间复杂度就都是O(1)了。
同时链表还保存了链表长度len,这样获取链表长度操作LLEN的时间复杂度也是O(1)。
迭代器
typedef struct listIter { listNode *next; int direction; } listIter;
adlist还通过listIter来实现了迭代器,通过next指向下一个节点,通过direction来指示迭代器迭代的方向。其中direction可以为AL_START_HEAD(从头节点开始)和AL_START_TAIL(从尾部节点开始)
获取迭代器的方法如下:
listIter *listGetIterator(list *list, int direction) { listIter *iter; if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL; if (direction == AL_START_HEAD) iter->next = list->head; else iter->next = list->tail; iter->direction = direction; return iter; }
然后就可以通过next函数利用迭代器遍历链表了
listNode *listNext(listIter *iter) { listNode *current = iter->next; if (current != NULL) { if (iter->direction == AL_START_HEAD) iter->next = current->next; else iter->next = current->prev; } return current; }
示意图
一个双向链表的示意图如下:链表的特点:
1、双向2、无环
3、带头节点和尾部节点
4、带链表长度
5、多态,通过void *来保存数据,并通过list结构中的dup、free、match函数指针为不同类型的数据设置特定的函数。因此链表可以用于保存不同类型的数据
本文所引用的源码全部来自Redis3.0.7版本。
相关文章推荐
- Redis主从复制和集群配置
- Redis主从复制和集群配置
- Redis主从复制和集群配置
- Redis源码解析——统计二进制数中1的个数
- redis实现跨服务器session共享
- redis学习笔记(1)---字符串sds
- linux下php redis扩展安装
- 阿里云Redis云数据库用户交流会
- redis 基本命令学习三(键值相关命令及服务器相关命令)
- Java中使用Jedis操作Redis
- 在windows上部署使用Redis
- redis的aof持久化深入解析
- Redis启动多端口、运行多实例
- zabbix监控redis多实例(low level discovery)
- Thinkphp S方法的redis配置
- yum 安装redis
- 五、SpringBoot JPA 配置redis
- Redis 起步
- Redis脚本使用总结
- redis 部分操作