Radix樹,即基數樹,也稱壓縮前綴樹,是一種提供key-value存儲查找的數據結構。與Trie不一樣的是,它對Trie樹進行了空間優化,只有一個子節點的中間節點將被壓縮。一樣的,Radix樹的插入、查詢、刪除操做的時間複雜度都爲O(k)。數據庫
通常由根節點、中間節點和葉子節點組成。
每一個節點能夠包含一個或多個字符。
樹的葉子結點數便是數據條目數。
從根節點到某一節點通過路徑的字符連起來即爲該節點對應的字符串。
每一個節點的全部子節點字符串都不相同。數組
對於長整型數據的映射。怎樣解決Hash衝突和Hash表大小的設計是一個很是頭疼的問題。緩存
radix樹就是針對這樣的稀疏的長整型數據查找,能高速且節省空間地完畢映射。藉助於Radix樹,咱們可以實現對於長整型數據類型的路由。 網絡
利用radix樹可以依據一個長整型(比方一個長ID)高速查找到其相應的對象指針。這比用hash映射來的簡單,也更節省空間,使用hash映射hash函數難以設計,不恰當的hash函數可能增大沖突,或浪費空間。數據結構
radix tree是一種多叉搜索樹。樹的葉子結點是實際的數據條目。每個結點有一個固定的、2^n指針指向子結點(每個指針稱爲槽slot,n爲劃分的基的大小)函數
Linux基數樹(radix tree)是將long整數鍵值與指針相關聯的機制,它存儲有效率。並且可高速查詢,用於整數值與指針的映射(如:IDR機制)、內存管理等。優化
IDR機制使用radix樹狀結構做爲由id進行索引獲取指針的稀疏數組,經過使用位圖可以高速分配新的ID,IDR機制避免了使用固定尺寸的數組存放指針。IDR機制的API函數在lib/idr.c中實現。編碼
Linux內核利用radix樹在文件內偏移高速定位文件緩存頁。 加密
Linux(2.6.7) 內核中的分叉爲 64(2^6)。樹高爲 6(64位系統)或者 11(32位系統),用來高速定位 32 位或者 64 位偏移,radix tree 中的每一個葉子節點指向文件內相應偏移所相應的Cache項。spa
【radix樹爲稀疏樹提供了有效的存儲,取代固定尺寸數組提供了鍵值到指針的高速查找。】
基數樹另外一個主要的缺陷是低效。即便你只想存一個鍵值對,但其中的鍵長度有幾百字符長,那麼每一個字符的那個層級你都須要大量的額外空間。每次查找和刪除都會有上百個步驟。在這裏咱們引入Patricia樹來解決這個問題。
Patricia樹,或稱Patricia trie,或 crit bit tree,壓縮前綴樹,是一種更節省空間的Trie。對於基數樹的每一個節點,若是該節點是惟一的兒子的話,就和父節點合併。
Merkle Tree,一般也被稱做Hash Tree,顧名思義,就是存儲hash值的一棵樹。Merkle樹的葉子是數據塊(例如,文件或者文件的集合)的hash值。非葉節點是其對應子節點串聯字符串的hash。
Merkle Tree 由 Hash List演化而來:在點對點網絡中做數據傳輸的時候,會同時從多個機器上下載數據,並且不少機器能夠認爲是不穩定或者不可信的。爲了校驗數據的完整性,更好的辦法是把大的文件分割成小的數據塊(例如,把分割成2K爲單位的數據塊)。這樣的好處是,若是小塊數據在傳輸過程當中損壞了,那麼只要從新下載這一快數據就好了,不用從新下載整個文件。
怎麼肯定小的數據塊沒有損壞哪?只須要爲每一個數據塊作Hash。BT下載的時候,在下載到真正數據以前,咱們會先下載一個Hash列表。那麼問題又來了,怎麼肯定這個Hash列表自己是正確的哪?答案是把每一個小塊數據的Hash值拼到一塊兒,而後對這個長字符串在做一次Hash運算,這樣就獲得Hash列表的根Hash(Top Hash or Root Hash)。下載數據的時候,首先從可信的數據源獲得正確的根Hash,就能夠用它來校驗Hash列表了,而後經過校驗後的Hash列表校驗數據塊。
Merkle Tree 能夠看作Hash List的泛化(Hash List能夠看做一種特殊的Merkle Tree,即樹高爲2的多叉Merkle Tree。
在最底層,和哈希列表同樣,咱們把數據分紅小的數據塊,有相應地哈希和它對應。可是往上走,並非直接去運算根哈希,而是把相鄰的兩個哈希合併成一個字符串,而後運算這個字符串的哈希,這樣每兩個哈希就結婚生子,獲得了一個」子哈希「。若是最底層的哈希總數是單數,那到最後必然出現一個單身哈希,這種狀況就直接對它進行哈希運算,因此也能獲得它的子哈希。因而往上推,依然是同樣的方式,能夠獲得數目更少的新一級哈希,最終必然造成一棵倒掛的樹,到了樹根的這個位置,這一代就剩下一個根哈希了,咱們把它叫作 Merkle Root。
在p2p網絡下載網絡以前,先從可信的源得到文件的Merkle Tree樹根。一旦得到了樹根,就能夠從其餘從不可信的源獲取Merkle tree。經過可信的樹根來檢查接受到的MerkleTree。若是Merkle Tree是損壞的或者虛假的,就從其餘源得到另外一個Merkle Tree,直到得到一個與可信樹根匹配的MerkleTree。
Merkle Tree和HashList的主要區別是,能夠直接下載並當即驗證 Merkle Tree的一個分支。由於能夠將文件切分紅小的數據塊,這樣若是有一塊數據損壞,僅僅從新下載這個數據塊就好了。若是文件很是大,那麼Merkle tree和Hash list都很到,可是Merkle tree能夠一次下載一個分支,而後當即驗證這個分支,若是分支驗證經過,就能夠下載數據了。而Hash list只有下載整個hash list才能驗證。
MPT(Merkle Patricia Tree)就是這二者混合的數據結構。
Merkle Patricia Tree
,梅克爾帕特里夏樹,提供了一個基於加密學的,自校驗防篡改的數據結構,用來存儲鍵值對關係。後文中將簡稱爲MPT
。儘管在本規範範圍內,咱們限定鍵值的類型只能是字符串(但仍對全部的類型適用,由於只需提供一個簡單的序列化和反序化機制,將要存儲的類型與字符串進行轉換便可)。
MPT
是肯定的。肯定性是指一樣內容的鍵值,將被保證找到一樣的結果,有一樣的根哈希。關於效率方面,對樹的插入,查找,刪除的時間複雜度控制在O(log(n))
。相較於紅黑樹來講,MPT
更好理解和編碼實現。
MPT樹中的節點包括空節點、葉子節點、擴展節點和分支節點:
空節點,簡單的表示空,在代碼中是一個空串。
葉子節點(leaf),表示爲[key,value]的一個鍵值對,其中key是key的一種特殊十六進制編碼,value是value的RLP編碼。
擴展節點(extension),也是[key,value]的一個鍵值對,可是這裏的value是其餘節點的hash值,這個hash能夠被用來查詢數據庫中的節點。也就是說經過hash連接到其餘節點。
分支節點(branch),由於MPT樹中的key被編碼成一種特殊的16進制的表示,再加上最後的value,因此分支節點是一個長度爲17的list,前16個元素對應着key中的16個可能的十六進制字符,若是有一個[key,value]對在這個分支節點終止,最後一個元素表明一個值,即分支節點既能夠搜索路徑的終止也能夠是路徑的中間節點。
MPT 樹中另外一個重要的概念是十六進制前綴(hex-prefix, HP)編碼,用來對key進行編碼。由於字母表是16進制的,因此每一個節點可能有16個孩子。由於有兩種[key,value]節點(葉節點和擴展節點),引進一種特殊的終止符標識來標識key所對應的是值是真實的值,仍是其餘節點的hash。若是終止符標記被打開,那麼key對應的是葉節點,對應的值是真實的value。若是終止符標記被關閉,那麼值就是用於在數據塊中查詢對應的節點的hash。
參看地址:https://blog.csdn.net/smilejiasmile/article/details/82843278#_169