redis 字首樹 基數樹 底層實現 rax

2021-10-01 07:43:17 字數 3706 閱讀 8302

以後都在 github 更新,請戳 rax(redis 實現的字首樹)

rax是 redis 自己實現的基數樹, 它是一種基於儲存空間優化的字首樹資料結構, 在 redis 的許多地方都有使用到, 比如streams這個型別裡面的consumer group(消費者組) 的名稱還有集群名稱

ok通常來講, 乙個基數樹(字首樹) 看起來如下所示

* 這是最基本的表示方式:

* * (f) ""

* \

* (o) "f"

* \

* (o) "fo"

* \

* [t b] "foo"

* / \

* "foot" (e) (a) "foob"

* / \

* "foote" (r) (r) "fooba"

* / \

* "footer" "foobar"

*

翻譯自redis/src/rax.h

然而, 當前的**實現使用了一種非常常見的優化策略, 把只有單個子的節點連續幾個節點壓縮成乙個節點, 這個節點有乙個字串, 不再是只儲存單個字元, 上述的結構可以優化成如下結構

*

* ["foo"] ""

* |

* [t b] "foo"

* / \

* "foot" ("er") ("ar") "foob"

* / \

* "footer" "foobar"

字串mygroup1在 rax 中也是以壓縮節點的方式儲存的, 可以用如下表示

*

* ["mygroup1"] ""

* |

* "mygroup1"

第乙個節點儲存了壓縮過的整個字串mygroup1, 第二個節點是乙個空的葉子節點, 他是乙個 key 值, 表示到這個節點之前合起來的字串儲存在了當前的rax結構中

下圖是字串mygroup1當前所在的rax的實際圖示, 並且 key 節點中的 data 字段儲存了乙個指標, 這個指標指向了和mygroup1相對應的consumer group物件

iskey表示當前的節點是否為 key 節點

isnull表示當前節點是否有儲存額外的值(比如上面的consumer group物件)

iscompr表示當前節點是否為壓縮的節點

size是子節點數量或者壓縮的字串長度

第乙個節點的iscompr值為 1, 並且整個字串mygroup1儲存在了當前這乙個節點中,size為 8 表示當前節點儲存了 8 個char字元,iskey為 0, 表示當前的節點不是 key 節點, 我們需要繼續往下搜尋

第二個節點的iskey為 1, 表示當前的節點為 key 節點, 它表示在到這個節點之前的所有字串連起來(也就是mygroup1) 存在當前的字首樹中, 也就是說當前的字首樹有包含mygroup1這個字串,isnull為 0 表示在當前這個 key 節點的 data 尾部儲存了乙個指標, 這個指標是函式呼叫者進行儲存的, 在當前的情況它是乙個指向streamcg的指標, 但是實際上他可以是指向任意物件的指標, 比如集群名稱或者其他物件

我們再來插入乙個consumer group名稱到當前的字首樹中

從上圖可知, 第乙個節點被裁剪了, 並且它後面插入了乙個新的節點, 左下角的節點是原先存在的節點, 右下角的節點也是乙個新插入的節點

*

* ["mygroup"] ""

* |

* [1 2] "mygroup"

* / \

* "mygroup1" "mygroup2"

中間的節點未被壓縮(iscompr這個位沒有被設定), data 欄位中儲存了size個字元, 在這些字元之後, 同樣會儲存size個指向與之前字元一一對應的raxnode的結構的指標

底下兩個節點的iskey = 1isnull = 0, 表示當到達任意乙個這樣的節點時, 當前的字串是儲存在這個字首樹中的, 並且在 data 欄位最尾部儲存了乙個輔助的指標, 這個指標具體指向什麼物件取決於呼叫者

如果你對rax的插入或者刪除演算法感興趣, 請閱讀以下**

redis/src/rax.c中的raxgenericinsertredis/src/rax.c中的raxremove

基數樹(wikipedia)

rax, an ansi c radix tree implementation

字首樹 java實現)

package class 07 字首樹 例子 乙個字串型別的陣列arr1,另乙個字串型別的陣列arr2。arr2中有哪些字元,是arr1中出現的?請列印 arr2中有哪些字元,是作為arr1中某個字串字首出現的?請列印 arr2中有哪些字元,是作為arr1中某個字串字首出現的?請列印arr2中出現...

字首樹python實現

file name 字首樹.py class trienode object def init self self.path 0 路過此節點幾個 self.end 0 以此為結尾的幾個 self.map none for i in range 26 每乙個節點有26條路 class trie obj...

字首樹 字典樹

trie 樹是乙個有根的樹,其結點具有以下字段 最多 rr 個指向子結點的鏈結,其中每個鏈結對應字母表資料集中的乙個字母。本文中假定 rr 為 26,小寫拉丁字母的數量。布林字段,以指定節點是對應鍵的結尾還是只是鍵字首。trie 發音為 try 或字首樹是一種樹資料結構,用於檢索字串資料集中的鍵。這...