看圖輕鬆理解資料結構與演算法系列(Radix樹)

超人汪小建發表於2019-03-01

前言

推出一個新系列,《看圖輕鬆理解資料結構和演算法》,主要使用圖片來描述常見的資料結構和演算法,輕鬆閱讀並理解掌握。本系列包括各種堆、各種佇列、各種列表、各種樹、各種圖、各種排序等等幾十篇的樣子。

Radix樹

Radix樹,即基數樹,也稱壓縮字首樹,是一種提供key-value儲存查詢的資料結構。與Trie不同的是,它對Trie樹進行了空間優化,只有一個子節點的中間節點將被壓縮。同樣的,Radix樹的插入、查詢、刪除操作的時間複雜度都為O(k)。

Radix樹特點

  • 一般由根節點、中間節點和葉子節點組成。
  • 每個節點可以包含一個或多個字元。
  • 樹的葉子結點數即是資料條目數。
  • 從根節點到某一節點經過路徑的字元連起來即為該節點對應的字串。
  • 每個節點的所有子節點字串都不相同。

插入操作

對romane、romanus、romulus、rubens、ruber、rubicon、rubicundus七個字串進行插入,開始插入romane,此時樹為空,直接建立一個“romane”節點,並將該節點結束標記設為true,隨即完成romane的插入。

image

接著插入romanus,此時根節點已經不為空,於是從根節點開始逐個字元進行比較,發現兩者字首“roman”相同,需要分割原來的“romane”節點,先建立一個新的公共字首“roman”節點,

image

然後將原來的“romane”節點設為“e”,“e”是“romane”除去公共字首“roman”後剩下的字元,並將新的公共字首節點指向“e”子節點,子節點索引為“e”。

image

接著繼續建立一個新的“us”節點,“us”是“romanus”除去公共字首“roman”後剩下的字元,

image

最後將公共字首“roman”節點指向“us”子節點,索引為“u”,並將“us”節點結束標記設為true。

image

往下插入romulus,從根節點開始逐個字元進行比較,發現兩者字首“rom”相同,需要分割原來的“roman”節點,先建立一個新的公共字首“rom”節點,

image

然後將原來的“roman”節點設為“an”,“an”是“roman”除去公共字首“rom”後剩下的字元,並將新的公共字首節點指向“an”子節點,子節點索引為“a”。

image

接著繼續建立一個新的“ulus”節點,“ulus”是“romulus”除去公共字首“rom”後剩下的字元,

image

最後將公共字首“rom”節點指向“ulus”子節點,索引為“u”,並將“ulus”節點結束標記設為true。

image

繼續插入rubens,從根節點開始逐個字元進行比較,發現兩者字首“r”相同,需要分割原來的“rom”節點,先建立一個新的公共字首“r”節點,

image

然後將原來的“rom”節點設為“om”,“om”是“rom”除去公共字首“r”後剩下的字元,並將新的公共字首節點指向“om”子節點,子節點索引為“o”。

image

接著繼續建立一個新的“ubens”節點,“ubens”是“rubens”除去公共字首“r”後剩下的字元,

image

最後將公共字首“r”節點指向“ubens”子節點,索引為“u”,並將“ubens”節點結束標記設為true。

image

繼續插入ruber,從根節點開始逐個字元進行比較,發現比較完“r”後根節點已經沒有值可以比較了,於是開始找“r”節點的子節點,

image

根據第二個字元“u”找到對應的子節點,即“ubens”節點,

image

剩餘的“uber”字串繼續與該節點進行逐一比較,發現兩者字首“ube”相同,需要分割原來的“ubens”節點,先建立一個新的公共字首“ube”節點,

image

然後將原來的“ubens”節點設為“ns”,“ns”是“ubens”除去公共字首“ube”後剩下的字元,並將新的公共字首節點指向“ns”子節點,索引為“n”,此外,原來指向“ubens”節點的“u”索引指向“ube”節點。

image

接著繼續建立一個新的“r”節點,“r”是“ruber”除去公共字首“r”和“ube”後剩下的字元,

image

最後將公共字首“ube”節點指向“r”子節點,索引為“r”,並將“r”節點結束標記設為true。

image

類似地,將rubicon插入樹中,結果如下。

image

繼續插入rubicundus,結果如下。

image

查詢操作

假如查詢ruok,從根節點開始比較,“r”相等且根節點已經沒有值可以繼續比較,

image

於是根據“u”索引找下一個子節點,在“ub”子節點中繼續逐一字元比較,

image

發現沒法匹配上“uok”,不存在“ruok”,於是查詢結束。

假如查詢rubicon,從根節點開始比較,“r”相等且根節點已經沒有值可以繼續比較,

image

於是根據“u”索引找下一個子節點,在“ub”子節點中繼續逐一字元比較,

image

比較完該節點後繼續根據“i”索引找子節點,在“ic”節點中繼續逐一字元比較,

image

比較完該節點後繼續根據“o”索引找子節點,在“on”節點中繼續逐一字元比較,此時“rubicon”已經完成所有字元的比較,而且“on”節點的結束標記為true,也就是說存在“rubicon”字串,查詢結束。

image

假如查詢roman,從根節點開始比較,“r”相等且根節點已經沒有值可以繼續比較,

image

於是根據“o”索引找下一個子節點,在“om”子節點中繼續逐一字元比較,

image

比較完該節點後繼續根據“a”索引找子節點,在“an”節點中繼續逐一字元比較,此時“roman”已經完成所有字元的比較,但“an”節點的結束標記為false,所以“roman”字串不存在,查詢結束。

image

————-推薦閱讀————

我的開源專案彙總(機器&深度學習、NLP、網路IO、AIML、mysql協議、chatbot)

為什麼寫《Tomcat核心設計剖析》

我的2017文章彙總——機器學習篇

我的2017文章彙總——Java及中介軟體

我的2017文章彙總——深度學習篇

我的2017文章彙總——JDK原始碼篇

我的2017文章彙總——自然語言處理篇

我的2017文章彙總——Java併發篇


跟我交流,向我提問:

看圖輕鬆理解資料結構與演算法系列(Radix樹)

歡迎關注:

看圖輕鬆理解資料結構與演算法系列(Radix樹)

相關文章