树:BST、AVL、红黑树、B树、B+树

咱们这个专题介绍的动态查找树主要有: 二叉查找树(BST),平衡二叉查找树(AVL),红黑树(RBT),B~/B+树(B-tree)。这四种树都具有下面几个优点:算法

(1) 都是动态结构。在删除,插入操做的时候,都不须要完全重建原始的索引树。最多就是执行必定量的旋转,变色操做来有限的改变树的形态。而这些操做所付出的代价都远远小于重建一棵树。这一优点在《查找结构专题(1):静态查找结构概论 》中讲到过。数据库

(2) 查找的时间复杂度大致维持在O(log(N))数量级上。可能有些结构在最差的状况下效率将会降低很快,好比BST。这个会在下面的对比中详细阐述。性能

下面咱们开始归纳性描述这四种树,并相互比较一下优劣。优化

 

1. 二叉查找树  (Binary Search Tree)   spa

    很显然,二叉查找树的发现彻底是由于静态查找结构在动态插入,删除结点所表现出来的无能为力(须要付出极大的代价)。指针

   BST 的操做代价分析:blog

    (1) 查找代价: 任何一个数据的查找过程都须要从根结点出发,沿某一个路径朝叶子结点前进。所以查找中数据比较次数与树的形态密切相关。索引

         当树中每一个结点左右子树高度大体相同时,树高为logN。则平均查找长度与logN成正比,查找的平均时间复杂度在O(logN)数量级上。内存

         当前后插入的关键字有序时,BST退化成单支树结构。此时树高n。平均查找长度为(n+1)/2,查找的平均时间复杂度在O(N)数量级上。字符串

    (2) 插入代价: 新结点插入到树的叶子上,彻底不须要改变树中原有结点的组织结构。插入一个结点的代价与查找一个不存在的数据的代价彻底相同。

    (3) 删除代价: 当删除一个结点P,首先须要定位到这个结点P,这个过程须要一个查找的代价。而后稍微改变一下树的形态。若是被删除结点的左、右子树只有一个存在,则改变形态的代价仅为O(1)。若是被删除结点的左、右子树均存在,只须要将当P的左孩子的右孩子的右孩子的...的右叶子结点与P互换,在改变一些左右子树便可。所以删除操做的时间复杂度最大不会超过O(logN)。

    BST效率总结 :  查找最好时间复杂度O(logN),最坏时间复杂度O(N)。

                            插入删除操做算法简单,时间复杂度与查找差很少

 

2. 平衡二叉查找树 ( Balanced Binary Search Tree ) 

    二叉查找树在最差状况下居然和顺序查找效率至关,这是没法仍受的。事实也证实,当存储数据足够大的时候,树的结构对某些关键字的查找效率影响很大。固然,形成这种状况的主要缘由就是BST不够平衡(左右子树高度差太大)。

    既然如此,那么咱们就须要经过必定的算法,将不平衡树改变成平衡树。所以,AVL树就诞生了。

    AVL 的操做代价分析:

    (1) 查找代价: AVL是严格平衡的BST(平衡因子不超过1)。那么查找过程与BST同样,只是AVL不会出现最差状况的BST(单支树)。所以查找效率最好,最坏状况都是O(logN)数量级的。

    (2) 插入代价: AVL必需要保证严格平衡(|bf|<=1),那么每一次插入数据使得AVL中某些结点的平衡因子超过1就必须进行旋转操做。事实上,AVL的每一次插入结点操做最多只须要旋转1次(单旋转或双旋转)。所以,整体上插入操做的代价仍然在O(logN)级别上(插入结点须要首先查找插入的位置)。

    (3) 删除代价:AVL删除结点的算法能够参见BST的删除结点,可是删除以后必须检查从删除结点开始到根结点路径上的全部结点的平衡因子。所以删除的代价稍微要大一些。每一次删除操做最多须要O(logN)次旋转。所以,删除操做的时间复杂度为O(logN)+O(logN)=O(2logN)

    AVL 效率总结 :  查找的时间复杂度维持在O(logN),不会出现最差状况

                            AVL树在执行每一个插入操做时最多须要1次旋转,其时间复杂度在O(logN)左右。

                            AVL树在执行删除时代价稍大,执行每一个删除操做的时间复杂度须要O(2logN)。

 

3. 红黑树 (Red-Black Tree ) 

    二叉平衡树的严格平衡策略以牺牲创建查找结构(插入,删除操做)的代价,换来了稳定的O(logN) 的查找时间复杂度。可是这样作是否值得呢?

    能不能找一种折中策略,即不牺牲太大的创建查找结构的代价,也能保证稳定高效的查找效率呢? 答案就是:红黑树。

   重要特色:

 1. 每一个红色结点的两个子节点必须是黑色的。换句话说:从每一个叶子到根的全部路径上不能有两个连续的红色结点

   2.从任一结点到其每一个叶子的全部路径都包含相同数目的黑色结点

   因此, 从根到叶子的最长的可能路径很少于最短的可能路径的两倍长。

    RBT 的操做代价分析:

     (1) 查找代价:因为红黑树的性质(最长路径长度不超过最短路径长度的2倍),能够说明红黑树虽然不像AVL同样是严格平衡的,但平衡性能仍是要比BST要好。其查找代价基本维持在O(logN)左右,但在最差状况下(最长路径是最短路径的2倍少1),比AVL要略逊色一点。

    (2) 插入代价:RBT插入结点时,须要旋转操做和变色操做。但因为只须要保证RBT基本平衡就能够了。所以插入结点最多只须要2次旋转,这一点和AVL的插入操做同样。虽然变色操做须要O(logN),可是变色操做十分简单,代价很小。

    (3) 删除代价:RBT的删除操做代价要比AVL要好的多,删除一个结点最多只须要3次旋转操做。

    RBT 效率总结 : 查找 效率最好状况下时间复杂度为O(logN),但在最坏状况下比AVL要差一些,但也远远好于BST。

                           插入和删除操做改变树的平衡性的几率要远远小于AVL(RBT不是高度平衡的)。所以须要的旋转操做的可能性要小,并且一旦须要旋转,插入一个结点最多只须要旋转2次,删除最多只须要旋转3次(小于AVL的删除操做所须要的旋转次数)。虽然变色操做的时间复杂度在O(logN),可是实际上,这种操做因为简单所须要的代价很小。

 

4. B~树/B+树 (B-Tree ) 

     对于在内存中的查找结构而言,红黑树的效率已经很是好了(实际上不少实际应用还对RBT进行了优化)。可是若是是数据量很是大的查找呢?将这些数据所有放入内存组织成RBT结构显然是不实际的。实际上,像OS中的文件目录存储,数据库中的文件索引结构的存储.... 都不可能在内存中创建查找结构。必须在磁盘中创建好这个结构。那么在这个背景下,RBT仍是一种好的选择吗?

     在磁盘中组织查找结构,从任何一个结点指向其余结点都有可能读取一次磁盘数据,再将数据写入内存进行比较。你们都知道,频繁的磁盘IO操做,效率是很低下的(机械运动比电子运动要慢不知道多少)。显而易见,全部的二叉树的查找结构在磁盘中都是低效的。所以,B树很好的解决了这一个问题。

    B-Tree的操做代价分析:

    (1) 查找代价: B-Tree做为一个平衡多路查找树(m-叉)。B树的查找分红两种:一种是从一个结点查找另外一结点的地址的时候,须要定位磁盘地址(查找地址),查找代价极高。另外一种是将结点中的有序关键字序列放入内存,进行优化查找(能够用折半),相比查找代价极低。而B树的高度很小,所以在这一背景下,B树比任何二叉结构查找树的效率都要高不少。并且B+树做为B树的变种,其查找效率更高。

    (2)插入代价: B-Tree的插入会发生结点的分裂操做。当插入操做引发了s个节点的分裂时,磁盘访问的次数为h(读取搜索路径上的节点)+2s(回写两个分裂出的新节点)+1(回写新的根节点或插入后没有致使分裂的节点)。所以,所须要的磁盘访问次数是h+2s+1,最多可达到3h+1。所以插入的代价是很大的。

    (3)删除代价:B-Tree的删除会发生结点合并操做。最坏状况下磁盘访问次数是3h=(找到包含被删除元素须要h次
读访问)+(获取第2至h层的最相邻兄弟须要h-1次读访问)+(在第3至h层的合并须要h-2次写
访问)+(对修改过的根节点和第2层的两个节点进行3次写访问)

   B-Tree效率总结: 因为考虑磁盘储存结构,B树的查找、删除、插入的代价都远远要小于任何二叉结构树(读写磁盘次数的下降)。

动态查找树结构的对比:

(1) 平衡二叉树和红黑树  [AVL  PK  RBT]

      AVL 和RBT 都是二叉查找树的优化。其性能要远远好于二叉查找树。他们之间都有本身的优点,其应用上也有不一样。

      结构对比: AVL的结构高度平衡,RBT的结构基本平衡。平衡度AVL > RBT.

      查找对比: AVL 查找时间复杂度最好,最坏状况都是O(logN)。

                      RBT 查找时间复杂度最好为O(logN),最坏状况下比AVL略差。

      插入删除对比:  1. AVL的插入和删除结点很容易形成树结构的不平衡,而RBT的平衡度要求较低。所以在大量数据插入的状况下,RBT须要经过旋转变色操做来从新达到平衡的频度要小于AVL。

                             2. 若是须要平衡处理时,RBT比AVL多一种变色操做,并且变色的时间复杂度在O(logN)数量级上。可是因为操做简单,因此在实践中这种变色仍然是很是快速的。

                             3. 当插入一个结点都引发了树的不平衡,AVL和RBT都最多须要2次旋转操做。但删除一个结点引发不平衡后,AVL最多须要logN 次旋转操做,而RBT最多只须要3次。所以二者插入一个结点的代价差很少,但删除一个结点的代价RBT要低一些。

                             4. AVL和RBT的插入删除代价主要仍是消耗在查找待操做的结点上。所以时间复杂度基本上都是与O(logN) 成正比的。

        整体评价:大量数据实践证实,RBT的整体统计性能要好于平衡二叉树。

(2) B~树和B+树    [ B~Tree   PK  B+Tree]

      B+树是B~树的一种变体,在磁盘查找结构中,B+树更适合文件系统的磁盘存储结构。

      结构对比: B~树是平衡多路查找树,全部结点中都包含了待查关键字的有效信息(好比文件磁盘指针)。每一个结点如有n个关键字,则有n+1个指向其余结点的指针。

                     B+树严格意义上说已经不是树,它的叶子结点之间也有指针连接。B+树的非终结点中并不含有关键字的信息,须要查找的关键字的所有信息都包含在叶子结点上。非终结点中只做为叶子结点关键字的索引而存在。

      查找对比:1. 在相同数量的待查数据下,B+树查找过程当中须要调用的磁盘IO操做要少于普通B~树。因为B树所在的磁盘存储背景下,所以B+树的查找性能要好于B~树。

                     2. B+树的查找效率更加稳定,由于全部叶子结点都处于同一层中,并且查找全部关键字都必须走完从根结点到叶子结点的所有历程。所以同一颗B+树中,任何关键字的查找比较次数都是同样的。而B树就不必定了,可能查找到某一个非终结点就结束了。

      插入删除对比:  B+树与B~树在插入删除操做中的效率是差很少的。

      整体评价:在应用背景下,特别是文件结构存储中。B+树的应用要更多,其效率也要比B~树好。

字符串查找结构

此次专题所讲的BST、AVL、BRT、B~Tree等能够胜任对任何关键字数据进行查找。但对字符串的查找(字符串匹配)结构,有专门的结构和算法。

相关文章
相关标签/搜索