二叉树、平衡二叉树、红黑树、B-树、B+树、B*树、T树之间的详解和比较

626 阅读19分钟

​ ====================================================||

欢迎讨论技术的可以相互加微信:windgs (请备注juejin+xx职业)

====================================================||

一、二叉树-BST  (binary search/sort tree) 二叉树又名二叉查找/搜索/排序树   或者是一棵空树; 或者是具有下列性质的二叉树: (1)若它的左子树不空,则左子树上所有结点的值均小于它的父结点的值; (2)若它的右子树不空,则右子树上所有结点的值均大于它的父结点的值; (3)它的左、右子树也分别为二叉排序树。 遍历:分为前序遍历、中序遍历(得到有序集合)、后续遍历

 

1.所有非叶子结点至多拥有两个儿子(Left和Right);

2.所有结点存储一个关键字;

3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;

 BST树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中;

否则,如果查询关键字比结点关键字小,就进入左儿子;如果比结点关键字大,就进入

右儿子;如果左儿子或右儿子的指针为空,则报告找不到相应的关键字;

       如果BST树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树

的搜索性能逼近二分查找;但它比连续内存空间的二分查找的优点是,改变BST树结构

(插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销;

右边也是一个BST树,但它的搜索性能已经是线性的了;同样的关键字集合有可能导致不同的

树结构索引;所以,使用BST树还要考虑尽可能让BST树保持左图的结构,和避免右图的结构,也就

是所谓的“平衡”问题;

二、平衡二叉树(Self-balancing binary search tree)   自平衡二叉查找树  又被称为AVL树(有别于AVL算法) 它是一棵空树或它的左右两个子树的高度差(平衡因子)的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,平衡二叉树必定是二叉搜索树,反之则不一定

 平衡因子(平衡度):平衡度为1,既每个结点的平衡因子都为 1、-1、0 的二叉排序树。或者说每个结点的左右子树的高度最多差1的二叉排序树。

平衡二叉树的目的是为了减少二叉查找树层次,提高查找速度

平衡二叉树的常用实现方法有AA树、AVL树、红黑树、树堆Treap、伸展树等

AVL 树是高度平衡的,频繁的插入和删除,会引起频繁的reblance,导致效率下降 红黑树不是高度平衡的,算是一种折中,插入最多两次旋转,删除最多三次旋转

AVL平衡二叉搜索树 定义:平衡二叉树或为空树,或为如下性质的二叉排序树:   (1)左右子树深度之差的绝对值不超过1;   (2)左右子树仍然为平衡二叉树. 平衡因子BF=左子树深度-右子树深度. 平衡二叉树每个结点的平衡因子只能是1,0,-1。若其绝对值超过1,则该二叉排序树就是不平衡的。 如图所示为平衡树和非平衡树示意图:

三、红黑树-R-B Tree,全称是Red-Black Tree 又称为“红黑树”,它一种平衡二叉树。红黑树的每个节点上都有存储位表示节点的颜色,可以是红(Red)或黑(Black)。 红黑树的特性: (1)每个节点或者是黑色,或者是红色。 (2)根节点是黑色。 (3)每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!] (4)如果一个节点是红色的,则它的子节点必须是黑色的。 (5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

注意: (01) 特性(3)中的叶子节点,是只为空(NIL或null)的节点。 (02) 特性(5),确保没有一条路径会比其他路径长出俩倍。因而,红黑树是相对是接近平衡的二叉树

四、B-树是一种多路搜索树(并不一定是二叉的) 一棵m阶B树(balanced tree of order m)是一棵平衡的m路搜索树。它或者是空树,或者是满足下列性质的树: 1、根结点至少有两个子女;

2、每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1;

3、除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:┌m/2┐ <= k <= m ;

4、所有的叶子结点都位于同一层。

特点: 是一种多路搜索树(并不是二叉的):

1.定义任意非叶子结点最多只有M个儿子;且M>2;

2.根结点的儿子数为[2, M];

3.除根结点以外的非叶子结点的儿子数为[M/2, M];

4.每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)

5.非叶子结点的关键字个数=指向儿子的指针个数-1;

6.非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];

7.非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的

子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树;

8.所有叶子结点位于同一层;

如:(M=3)

B-树的特性: 1.关键字集合分布在整颗树中;

2.任何一个关键字出现且只出现在一个结点中;

3.搜索有可能在非叶子结点结束;

4.其搜索性能等价于在关键字全集内做一次二分查找;

5.自动层次控制;

五、B+树 B+ 树是一种树数据结构,是一个n叉树,每个节点通常有多个孩子,一棵B+树包含根节点、内部节点和叶子节点。根节点可能是一个叶子节点,也可能是一个包含两个或两个以上孩子节点的节点。 用途: B+ 树通常用于数据库和操作系统的文件系统中。NTFS, ReiserFS, NSS, XFS, JFS, ReFS 和BFS等文件系统都在使用B+树作为元数据索引。B+ 树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。B+ 树元素自底向上插入。

B+树的定义 B+树是应文件系统所需而出的一种B-树的变型树。一棵m阶的B+树和m阶的B-树的差异在于: 1.有n棵子树的结点中含有n个关键字,每个关键字不保存数据,只用来索引,所有数据都保存在叶子节点。

2.所有的叶子结点中包含了全部关键字的信息,及指向含这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接。

3.所有的非终端结点可以看成是索引部分,结点中仅含其子树(根结点)中的最大(或最小)关键字。  通常在B+树上有两个头指针,一个指向根结点,一个指向关键字最小的叶子结点。

B+树是B-树的变体,也是一种多路搜索树: 1.其定义基本与B-树同,除了:

2.非叶子结点的子树指针与关键字个数相同;

3.非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树

(B-树是开区间);

5.为所有叶子结点增加一个链指针;

6.所有关键字都在叶子结点出现;  

B+的特性: 1.所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好

是有序的;

2.不可能在非叶子结点命中;

3.非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储

(关键字)数据的数据层;

4.更适合文件索引系统;

六、B*树: 是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;

B*树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3 (代替B+树的1/2); B+树的分裂: 当一个结点满时,分配一个新的结点,并将原结点中1/2的数据

复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父

结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针;

B*树的分裂:

当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分

数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字

(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之

间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针;

所以,B*树分配新结点的概率比B+树要低,空间使用率更高;

七、T-tree树-一个存储节点可以保存多个键值 1.T树相关概念      T树具有以下特点:

①左子树与右子树之差不超过1

②在一个存储节点可以保存多个键值,它的最左与最右键值分别为这个节点的最小与最大键值,它的左子树仅仅包含那些键值小于或等于最小键值的一记录,同理右子树只包括那些键值大于或等于最大键值的记录

③同时拥有左右子树的节点被称为内部节点,只拥有一个子树的节点被称为半叶一,没有子树的节点被称为叶子

④为了保持空间的利用率,每一个内部节点都需要包含一个最小数目的键值。由此可知T树是一个每个结点含有多个关键字的平衡二叉树,每个节点内的关键字有序排列,左子树都要比根节点关键字小,右子树都要比根节点关键字大。 在上述T树结点结构中,包含如下信息: (1) balance(平衡因子),其绝对值不大于1,balance =右子树高度-左子树高度; (2) Left_child_ptr和Right_child_ptr分别表示当前结点的左子树和右子树指针; (3) Max_Item表示结点中所能容纳的键值的最大数; (4)Key[0]至K[Max_Item-1]为结点内存放的关键字; (5)nItem是当前节点实际存储的关键字个数。

2.T树索引的操作       用T树作为索引方式主要完成三个工作:查找,插入,删除。其中插入和删除都是以查找为基础。下面分别介绍三种操作的流程。 (1)T树的查找类似于二叉树,不同之处主要在于每一结点上的比较不是针对结点中的各个元素值,而是首先检查所要查找的目标键值是否包含在当前结点的最左键值和最右键值所确定的范围内,如果是的话,则在当前结点的键值列表中使用二分法进行查找;如果目标键值小于当前结点的最左键值,则类似地搜索当前结点的左孩子结点;如果目标键值大于当前结点的最右键值,则类似地搜索当前结点的右孩子结点。  (2)T树的插入是以查找为基础,应用查找操作定位目标键值插入位置,并记下查找过程所遇到的最后结点。如果查找成功,判断此结点中是否有足够的存储空间。如果有,则将目标键值插入结点中;否则将目标键值插入此结点,然后将结点中的最左键值插入到它的左子树中(此时是递归插入操作),之后结束;否则分配新结点,并插入目标键值;然后根据目标键值与结点的最大最小键值之间的关系,将新分配的结点链接为结点的左孩子或右孩子;对树进行检查,判断T树的平衡因子是否满足条件,如果平衡因子不满足则执行旋转操作。

(3)T树的删除操作也是以查找为基础,应用查找操作定位目标键值。如果查找失败,则结束;否则令N为目标键值所在的结点,并从结点N中删除目标键值;删除节点后,如果结点N为空,则删除结点N,并对树的平衡因子进行检查,判断是否需要执行旋转操作;如果结点N中的键值数量少于最小值,则根据N的平衡因子决定从结点N的左子树中移出最大的键值或者右子树中移出最小值来填充。 

3.T树索引实现关键技术      实现T树索引即要实现T树的查找,插入和删除。其中又以查找为基础,对T树的维护也就是T树的旋转为关键。当由于插入或删除键值导致树的失衡,则要进行T树的旋转。使之重新达到平衡。      在插入情况下,需要依次对所有沿着从新创建结点到根结点路径中的结点进行检查,直到出现如下两种情况之一时中止:某个被检查结点的两个子树高度相等,此时不需要执行旋转操作;某个被检查结点的两个子树的高度之差大于1,此时对该结点仅需执行一次旋转操作即可。      在删除情况下,类似地需要依次对所有沿着从待删除结点的父结点到根结点路径中的结点进行检查,在检查过程中当发现某个结点的左右子树高度之差越界时,需要执行一次旋转操作。与插入操作不同的是,执行完旋转操作之后,检查过程不能中止,而是必须一直执行到检查完根结点。      由此可以看出,对于插入操作,最多只需要一次旋转操作即可使T树恢复到平衡状态;而对于删除操作则可能会引起向上的连锁反应,使高层结点发生旋转,因而可能需要进行多次旋转操作。      为了对T树进行平衡,需要进行旋转操作,旋转是T树中最关键也是最难的的操作,下面介绍T树旋转的技术。

旋转可分为四种情况:由左孩子的左子树的插入(或者删除)引起的旋转记为LL旋转,类似有LR,RR及RL旋转。插入时的情况与删除类似。

八、R-tree-空间索引数据结构 1、R-Tree数据结构 R-Tree是一种空间索引数据结构,下面做简要介绍:

(1)R-Tree是n 叉树,n称为R-Tree的扇(fan)。

(2)每个结点对应一个矩形。

(3)叶子结点上包含了小于等于n 的对象,其对应的矩为所有对象的外包矩形。

(4)非叶结点的矩形为所有子结点矩形的外包矩形。

R-Tree的定义很宽泛,同一套数据构造R-Tree,不同方可以得到差别很大的结构。什么样的结构比较优呢?有两标准:

(1)位置上相邻的结点尽量在树中聚集为一个父结点。

(2)同一层中各兄弟结点相交部分比例尽量小。

R树是一种用于处理多维数据的数据结构,用来访问二维或者更高维区域对象组成的空间数据.R树是一棵平衡树。树上有两类结点:叶子结点和非叶子结点。每一个结点由若干个索引项构成。对于叶子结点,索引项形如(Index,Obj_ID)。其中,Index表示包围空间数据对象的最小外接矩形MBR,Obj_ID标识一个空间数据对象。对于一个非叶子结点,它的索引项形如(Index,Child_Pointer)。 Child_Pointer 指向该结点的子结点。Index仍指一个矩形区域,该矩形区域包围了子结点上所有索引项MBR的最小矩形区域。

2、R-Tree空间索引算法

1、R-Tree-最小外接矩形 多维索引技术的历史可以追溯到20世纪70年代中期。就在那个时候,诸如Cell算法、四叉树和k-d树等各种索引技术纷纷问世,但它们的效果都不尽人意。在GIS和CAD系统对空间索引技术的需求推动下,Guttman于1984年提出了R树索引结构,发表了《R树:一种空间查询的动态索引结构》,它是一种高度平衡的树,由中间节点和页节点组成,实际数据对象的最小外接矩形存储在页节点中,中间节点通过聚集其低层节点的外接矩形形成,包含所有这些外接矩形。其后,人们在此基础上针对不同空间运算提出了不同改进,才形成了一个繁荣的索引树族,是目前流行的空间索引。

2、 R+树-兄弟结点对应的空间区域无重叠 在Guttman的工作的基础上,许多R树的变种被开发出来, Sellis等提出了R+树,R+树与R树类似,主要区别在于R+树中兄弟结点对应的空间区域无重叠,这样划分空间消除了R树因允许结点间的重叠而产生的“死区域”(一个结点内不含本结点数据的空白区域),减少了无效查询数,从而大大提高空间索引的效率,但对于插入、删除空间对象的操作,则由于操作要保证空间区域无重叠而效率降低。同时R+树对跨区域的空间物体的数据的存储是有冗余的,而且随着数据库中数据的增多,冗余信息会不断增长。Greene也提出了他的R树的变种。

3 R树-强制重新插入 在1990年,Beckman和Kriegel提出了最佳动态R树的变种——R树。R树和R树一样允许矩形的重叠,但在构造算法R树不仅考虑了索引空间的“面积”,而且还考虑了索引空间的重叠。该方法对结点的插入、分裂算法进行了改进,并采用“强制重新插入”的方法使树的结构得到优化。但R树算法仍然不能有效地降低空间的重叠程度,尤其是在数据量较大、空间维数增加时表现的更为明显。R树无法处理维数高于20的情况。

4 QR树-四叉树-结合了四叉树与R树的优势,是二者的综合应用 QR树利用四叉树将空间划分成一些子空间,在各子空间内使用许多R树索引,从而改良索引空间的重叠。QR树结合了四叉树与R树的优势,是二者的综合应用。实验证明:与R树相比,QR树以略大(有时甚至略小)的空间开销代价,换取了更高的性能,且索引目标数越多,QR树的整体性能越好。

5 SS树-用最小边界圆代替最小边界矩 SS树对R树进行了改进,通过以下措施提高了最邻近查询的性能:用最小边界圆代替最小边界矩形表示区域的形状,增强了最邻近查询的性能,减少将近一半存储空间;SS树改进了R树的强制重插机制。当维数增加到5是,R树及其变种中的边界矩形的重叠将达到90%,因此在高维情况(≧5)下,其性能将变的很差,甚至不如顺序扫描。

6 X树-用边界圆进行索引 X树是线性数组和层状的R树的杂合体,通过引入超级结点,大大地减少了最小边界矩形之间的重叠,提高了查询效率。X树用边界圆进行索引,边界矩形的直径(对角线)比边界圆大,SS树将点分到小直径区域。由于区域的直径对最邻近查询性能的影响较大,因此SS树的最邻近查询性能优于R树;边界矩形的平均容积比边界圆小,R树将点分到小容积区域;由于大的容积会产生较多的覆盖,因此边界矩形在容积方面要优于边界圆。SR树既采用了最小边界圆(MBS),也采用了最小边界矩形(MBR),相对于SS树,减小了区域的面积,提高了区域之间的分离性,相对于R*树,提高了邻近查询的性能。

小结: B树:二叉树,每个结点只存储一个关键字,等于则命中,小于走左结点,大于走右结点;

B-树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点;所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中;

B+树:在B-树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中;

B*树:在B+树基础上,为非叶子结点也增加兄弟节点链表指针,将结点的最低利用率从1/2提高到2/3;

B+/B*Tree应用:数据库索引--索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。数据库索引--表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。这个索引的key是数据表的主键