Redis內部數據結構詳解之雙向鏈表(linkedlist)

本文所引用的源碼全部來自Redis2.8.2版本。

Redis中linkedlist數據結構與API相關文件是adlist.c, adlist.h。

本文主要講解Redis中對雙向鏈表的詳細實現,以及相關API的分析,對於雙向鏈表本身可以從任意一本數據結構書本中得到詳解。

轉載請註明,來自:http://blog.csdn.net/acceptedxukai/article/details/17467373

一、雙向鏈表簡介

雙向鏈表作爲一種常見的數據結構,在嚴蔚敏數據結構書裏有詳細的講解,雙向鏈表的每個數據節點都有兩個指針,分別指向後繼與前驅節點,因此從雙向鏈表中的任意一個節點開始都可以很方便地訪問其前驅與後繼節點。

二、Redis中雙向鏈表數據結構以及相關宏定義

typedef struct listNode {
    struct listNode *prev;//前驅指針
    struct listNode *next;//後繼指針
    void *value; //節點的值
} listNode;

typedef struct listIter {//鏈表迭代器
    listNode *next;
    int direction;//遍歷方向
} listIter;

typedef struct list {//鏈表
    listNode *head;//鏈表頭
    listNode *tail;//鏈表尾
    void *(*dup)(void *ptr); //複製函數指針
    void (*free)(void *ptr); //釋放內存函數指針
    int (*match)(void *ptr, void *key); //比較函數指針
    unsigned long len; //鏈表長度
} list;

宏名稱

作用

listLength

獲取鏈表的長度值

listFirst

獲取鏈表的首指針

listLast

獲取鏈表的尾指針

listPrevNode

獲取當前節點的前驅節點指針

listNextNode

獲取當前節點的後繼節點指針

listNodeValue

獲取當前節點所存儲的值

listSetDupMethod

設置鏈表節點value的複製函數

listSetFreeMethod

設置鏈表節點value的釋放內存函數

listSetMatchMethod

設置鏈表節點value的比較函數

listGetDupMethod

獲取鏈表節點value的複製函數

listGetFree

獲取鏈表節點value的釋放內存函數

listGetMatchMethod

獲取鏈表節點value的比較函數

三、Redis中雙向鏈表API介紹

名稱

作用

複雜度

listCreate

創建一個新雙向鏈表

O(1)

listRelease

釋放一個雙向鏈表以及包含的節點內存

O(N)

listAddNodeHead

將一個節點添加到鏈表的表頭

O(1)

listAddNodeTail

將一個節點添加到鏈表的表尾

O(1)

listInsertNode

將一個節點添加到給定節點的之後或之前

O(1)

listDelNode

刪除給定的節點

O(1)

listGetIterator

生成雙向鏈表的迭代器

O(1)

listReleaseIterator

釋放雙向鏈表的迭代器

O(1)

listNext

通過迭代器獲取下一個節點

O(1)

listDup

創建給定鏈表的副本

O(N)

listSearchKey

查找與給定key相同值的節點

O(N)

listIndex

根據給定的索引值,返回相應的節點

O(N)

listRewind

重新初始化迭代器,迭代方向從頭至尾

O(1)

listRewindTail

重新初始化迭代器,迭代方向從尾至頭

O(1)

listRotate

取出鏈表尾節點並插入到頭部

O(1)

四、Redis雙向鏈表性能分析

Redis中的雙向鏈表也許是Redis中最簡單最容易實現的數據結構,對於API就不多說了,都很簡單,也沒啥可以說的,下面簡單分析一下雙向鏈表的性能。

listNode擁有prev前驅指針和next後繼指針,因此通過迭代器可以很方便的對鏈表從從頭至尾或從尾至頭遍歷;

list擁有header頭指針和tail爲指針,對於在鏈表的頭部或尾部進行插入節點的時間複雜度全部爲O(1),高效地實現了Redis中一些指令的操作;

list自帶保存鏈表長度的字段len,使得計算鏈表長度的時間複雜度爲O(1)。

五、小結

雙向鏈表主要有兩個作用:作爲Redis列表數據類型的底層實現方法之一;作爲通用數據結構可以被其他功能模塊使用。

雙向鏈表實現簡單,Redis對雙向鏈表加以改造,添加保存節點長度的字段,以及實現自己的迭代指針,使得一些數據操作變得簡單。

最後感謝黃健宏(huangz1990)的Redis設計與實現及其他對Redis2.6源碼的相關注釋對我在研究Redis2.8源碼方面的幫助。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章