1、二叉查找树(Binary Search Tree)
很显然,二叉查找树的发现完全是因为静态查找结构在动态插入,删除结点所表现出来的无能为力(需要付出极大的代价)。
BST 的操作代价分析:
(1) 查找代价: 任何一个数据的查找过程都需要从根结点出发,沿某一个路径朝叶子结点前进。因此查找中数据比较次数与树的形态密切相关。
当树中每个结点左右子树高度大致相同时,树高为logN。则平均查找长度与logN成正比,查找的平均时间复杂度在O(logN)数量级上。
当先后插入的关键字有序时,BST退化成单支树结构。此时树高n。平均查找长度为(n+1)/2,查找的平均时间复杂度在O(N)数量级上。
(2) 插入代价: 新结点插入到树的叶子上,完全不需要改变树中原有结点的组织结构。插入一个结点的代价与查找一个不存在的数据的代价完全相同。
(3) 删除代价: 当删除一个结点P,首先需要定位到这个结点P,这个过程需要一个查找的代价。然后稍微改变一下树的形态。如果被删除结点的左、右子树只有一个存在,则改变形态的代价仅为O(1)。如果被删除结点的左、右子树均存在,只需要将结点与互换,在改变一些左右子树即可。因此删除操作的时间复杂度最大不会超过O(N)。
BST效率总结 : 查找最好时间复杂度O(logN),最坏时间复杂度O(N)。
插入删除操作算法简单,时间复杂度与查找差不多
2、AVL树
二叉查找树在最差情况下竟然和顺序查找效率相当,这是无法仍受的。造成这种情况的主要原因就是BST不够平衡(左右子树高度差太大)。
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) 的查找时间复杂度。 红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。
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、平衡二叉树AVL VS 红黑树 [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的总体统计性能要好于平衡二叉树。
5、B~树 VS 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~树好。