1. 程式人生 > >redis源碼分析(3)-- 基本數據結構雙鏈表list

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

direction 函數指針 all eas 源碼 計數 type ima blog

一、雙鏈表結構

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的結構:

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

Redis鏈表list特點:

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

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

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

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

5、多態; 節點value為void*, 並且可以通過函數指針dup、free、match為節點設置屬性。

二、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;

三、鏈表操作

技術分享

技術分享

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