redis源碼分析(3)-- 基本數據結構雙鏈表list
阿新 • • 發佈:2017-07-23
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) { # 從叠代器依次獲取下個節點,並開始遍歷 8if (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