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、鏈表操做