redis源碼分析(3)-- 基本數據結構雙鏈表list

1、雙鏈表結構node

redis中實現的雙鏈表結構體以下:redis

1 typedef struct list {
2     listNode *head; # 鏈表頭
3     listNode *tail; # 鏈表尾
4     void *(*dup)(void *ptr); # 複製鏈表函數
5     void (*free)(void *ptr); # 釋放節點函數
6     int (*match)(void *ptr, void *key); # 匹配函數
7     unsigned long len; # 鏈表節點個數
8 } list;

包含三個節點的list組成如圖:函數

每一個listNode的結構:spa

1 typedef struct listNode {
2     struct listNode *prev;
3     struct listNode *next;
4     void *value;
5 } listNode;

Redis鏈表list特色:指針

一、雙端:每一個節點包括前向指針prev和後級指針next,獲取節點先後節點都是O(1)code

二、無環:首節點prev=NULL,尾節點next=NULLblog

三、list結構包含表頭指針和表尾指針,獲取頭尾節點時間複雜度O(1)源碼

四、list包含節點計數器len,獲取節點長度只須要O(1)it

五、多態; 節點value爲void*, 而且能夠經過函數指針dup、free、match爲節點設置屬性。io

 

2、list迭代器

鏈表其餘操做比較簡單,這裏主要介紹list中的迭代器使用。先看下迭代器在遍歷鏈表中的應用

 1 listNode *listSearchKey(list *list, void *key)
 2 {
 3     listIter *iter;
 4     listNode *node;
 5 
 6     iter = listGetIterator(list, AL_START_HEAD); # 獲取從頭開始的迭代器  7     while((node = listNext(iter)) != NULL) { # 從迭代器依次獲取下個節點,並開始遍歷  8         if (list->match) {
 9             if (list->match(node->value, key)) {
10                 listReleaseIterator(iter);
11                 return node;
12             }
13         } else {
14             if (key == node->value) {
15                 listReleaseIterator(iter);
16                 return node;
17             }
18         }
19     }
20     listReleaseIterator(iter); # 釋放迭代器 21     return NULL;
22 }

 獲取迭代器源碼:

 1 listIter *listGetIterator(list *list, int direction)
 2 {
 3     listIter *iter;
 4 
 5     if ((iter = zmalloc(sizeof(*iter))) == NULL) return NULL;
 6     if (direction == AL_START_HEAD) # 根據direction,獲得鏈表頭或者鏈表尾節點  7         iter->next = list->head;
 8     else
 9         iter->next = list->tail;
10     iter->direction = direction;
11     return iter;
12 }

迭代器結構:

1 typedef struct listIter {
2     listNode *next;
3     int direction;
4 } listIter;

3、鏈表操做

相關文章
相關標籤/搜索