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