字典也叫雜湊表。看一下redis中的實現。下面是資料結構關係圖。
redis中,雜湊表的設計思想是,申請乙個指標陣列,然後每個元素指向乙個鍊錶用來儲存資料(即鏈位址法)。
// 申請乙個表示字典的資料結構
dict *
dictcreate
(dicttype *type,
void
*privdataptr)
// 初始化字典資料結構
int_dictinit
(dict *ht, dicttype *type,
void
*privdataptr)
// 擴容
intdictresize
(dict *ht)
首先呼叫申請乙個dict結構體用來表示乙個字典。然後初始化他的相關字段,最後呼叫dictexpand開闢儲存資料的記憶體。
int
dictexpand
(dict *ht,
unsigned
long size)
}assert
(ht-
>used ==0)
;// 釋放舊的記憶體
_dictfree
(ht-
>table)
;// 覆蓋之前的資訊
*ht = n;
return dict_ok;
}
這樣就形成了乙個和文章開始那個圖一樣的結構。
int
dictadd
(dict *ht,
void
*key,
void
*val)
1 首先判斷key是否已經存在,存在的話就無法新增。
2 根據key和雜湊函式,計算對應的索引。
3 頭插法插入對應索引的鍊錶。
int
dictreplace
(dict *ht,
void
*key,
void
*val)
static
intdictgenericdelete
(dict *ht,
const
void
*key,
int nofree)
// 刪除這個節點
_dictfree
(he)
;// 已使用個數減一
ht->used--
;return dict_ok;
}// 儲存上乙個不匹配的
prevhe = he;
he = he-
>next;
}return dict_err;
/* not found */
}
首先根據key找到索引的對應的鍊錶,然後遍歷鍊錶找到key一樣的節點,最後就是從鍊錶中刪除乙個節點。
新增和刪除等操作都涉及到查詢元素,我們看看怎麼查詢。
dictentry *
dictfind
(dict *ht,
const
void
*key)
return
null
;}
我們可以看一下某個鉤子的實現。
// 雜湊函式
unsigned
intdictgenhashfunction
(const
unsigned
char
*buf,
int len)
// 比較函式
static
int_dictstringcopyhtkeycompare
(void
*privdata,
const
void
*key1,
const
void
*key2)
總來的流程就是根據key產生乙個索引,然後根據索引到雜湊表中取得對應的乙個鍊錶,然後操作這個鍊錶(新增,查詢,刪除)。
// 銷毀整個字典
int_dictclear
(dict *ht)
}/* free the table and the allocated cache structure */
// 釋放字典結構體
_dictfree
(ht-
>table)
;/* re-initialize the table */
// 重置字段
_dictreset
(ht)
;return dict_ok;
/* never fails */
}
該函式只是釋放字典裡儲存資料的記憶體,但是沒有釋放字典本身。下面函式可以釋放字典本身的記憶體。
// 釋放字典裡的資料和字典本身
void
dictrelease
(dict *ht)
7 迭代字典
redis中實現了各種迭代器對某種資料結構進行迭代,比如字典。
// 申請字典迭代器
dictiterator *
dictgetiterator
(dict *ht)
// 迭代字典的元素,每次呼叫返回乙個節點
dictentry *
dictnext
(dictiterator *iter)
else
// 還有節點,則同時記錄下乙個節,返回entry節點
if(iter-
>entry)
}return
null
;}
基本的邏輯就是,按照雜湊表陣列的索引,從小到大,每乙個索引,先去遍歷他對應的鍊錶,遍歷完後,繼續下乙個索引,直到最後乙個索引結束。
總結,redis的字典裡還有其他的一些方法,沒有一一枚舉。有興趣可以點這。
redis0 1原始碼解析之鍊錶
分析 之前先看看鍊錶的資料結構。新建乙個煉表頭結點 list listcreate void 釋放乙個鍊錶 void listrelease list list 釋放鍊錶記憶體 zfree list 3 插入乙個節點 支援頭插和尾插 給鍊錶新增乙個節點,頭插法 list listaddnodehea...
redis0 1原始碼解析之事件驅動
redis的事件驅動模組負責處理檔案和定時器兩種任務。下面是幾個函式指標 typedef void aefileproc struct aeeventloop eventloop,int fd,void clientdata,int mask typedef intaetimeproc struct...
Redis原始碼解析 字典結構
一般情況下,我們談到字典,難免要談到紅黑樹。但是redis這套字典庫並沒有使用該方案去實現,而是使用的是鍊錶,且整個 行數在1000行以內。所以這塊邏輯還是非常好分析的。我們可以想象下,如果使用普通的鍊錶去實現字典,那麼是不是整個資料都在一條鍊錶結構上呢?如果是這麼設計,插入和刪除操作是非常方便的,...