redis学习笔记(2)---链表adlist

来源:互联网 发布:opengl编程指南 第9版 编辑:程序博客网 时间:2024/05/17 22:00

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版本。

0 0
原创粉丝点击