做爲一種經常使用數據結構,鏈表內置在不少高級編程語言裏, 由於 C 語言沒有內置這種數據結構, Redis 構建了本身的鏈表實現.git
鏈表在 Redis 中的應用十分普遍, 好比列表鍵的底層實現之一就是鏈表. 當一個列表鍵包含了數量較多的元素,或者列表中包含的元素都是比較長的字符串時, Redis 就會使用鏈表做爲列表鍵的底層實現.
<!-- more -->
除了列表鍵以外, 發佈與訂閱、慢查詢、監視器等功能也用到了鏈表.還有使用鏈表來構建客戶端輸出緩衝區等.github
對於鏈表的定義和相關算法,不少算法書籍已經作了詳細的講解.這裏只對 Redis 中鏈表的實現作介紹.算法
每一個鏈表節點使用一個 listNode
結構來表示:編程
// file: adlist.h typedef struct listNode { struct listNode *prev; // 前置節點 struct listNode *next; //後置節點 void *value; //節點的值 } ListNode;
多個鏈表節點經過 prev
和 next
組成雙端鏈表,
Redis 使用 list
結構來管理鏈表:數據結構
typedef struct list { listNode *head; //表頭節點 listNode *tail; //表尾節點 unsigned long len; //鏈表的節點數量 void *(*dup) (void *ptr); //節點值複製函數 void (*free)(void *ptr); //節點值釋放函數 int (*match)(void *ptr, void *key); //節點值對比函數 } list;
下圖是由一個 lsit
結構和三個 ListNode
結構組成的鏈表.編程語言
Redis 的鏈表實現特性能夠總結以下:函數
雙端: 由於帶有 prev
和 next
指針,獲取某個節點的前置節點和後置節點的複雜度都是$O(1)$spa
無環: 表頭的 prev
指針和表尾的 next
指針均指向 NULL
, 對鏈表的訪問以 NULL
結束.指針
帶表頭指針和表尾指針: 經過 list
結構獲取表頭和表尾的複雜度爲$ O(1)$.code
帶鏈表長度計數器: list
結構的 len
屬性對鏈表節點的長度計數, 獲取鏈表中節點的數量複雜度爲$ O(1)$
多態: 鏈表節點使用 void *
指針來保存節點值, 而且能夠經過 list 結構的 dup
、free
、match
三個屬性爲節點值設置類型特定函數.鏈表能夠用於保存各類不一樣類型的值.
個人博客: http://ygmyth.github.io