树、二叉树、平衡二叉树、B树、B+树、红黑树各种常见树总结
基本概念与定义
树: 树是n个结点的有限集合,有且仅有一个根结点,其余结点可分为m个根结点的子树;
结点的度: 一个结点拥有子树的个数称为度;
树的深度: 树中结点的最大层次成为树的深度或高度;
权(Weight):树中结点的一个有某种意义的实数;
路径长度(Length):树的路径长度是从树根到树中每一结点的路径长度之和;
带权路径长度(WPL:Weighted Path Length Of Tree):
- 结点的WPL:结点到树根之间的路径长度与该结点上权的乘积
- 树的WPL:树中所有叶结点的带权路径长度之和
森林:树的集合称为森林;
二叉树:二叉树是每个节点最多拥有两个子节点的树,两个子节点分别成为左右节点;
满二叉树 :二叉树,高度为n,节点数为2^h-1,节点数都达到最大个数;
完全二叉树: 深度为h,1.除了h层其他层数的节点数都达到最大个数,2.第h层所有节点集中在左边,左连续;
最优二叉树/哈夫曼树: 带权路径长度达到最小的二叉树,权值较大的结点离根较近。
一. 二叉搜索树/查找树(BST:Binary Search Tree)
1.定义
- 二叉搜索树是二叉树中的一种情况,类似于排好序的二叉树,具有左节点和右节点,其中左结点小于根节点,右结点大于根节点;
- 一般用于索引,查找元素与二分查找相同,具有O(nlogn)的时间复杂度;
2.特点:
- 优点:相较于普通二叉树更便于树元素的索引;
- 缺点:极端情况下会形成线性链表的结构,时间复杂度就退化为O(n),解决方法为二叉平衡树;
3.构造
4.插入元素
二. 平衡二叉树(AVL树)
备注:AVL树得名于它的发明者Adelson-Velsky和Landis;
1.定义
- 本身首先是一棵二叉搜索树;
- 带有平衡条件:每个结点的左右子树的高度之差的绝对值小于等于(最多为)1;
2.特点
- 优点:AVL树的查找稳定,查找、插入、删除的时间复杂度都为O(logN);
- 缺点:由于要维持自身的平衡,所以进行插入和删除结点操作的时候,需要对结点进行频繁的旋转;AVL树当进行查找时,就需要多次磁盘IO,(数据是存放在磁盘中的,每次查询是将磁盘中的一页数据加入内存,树的每一层节点存放在一页中,不同层数据存放在不同页。)这样如果需要多层查询就需要多次磁盘IO。为了解决AVL树的这个问题,就出现了B树。
3.构造和插入元素
单旋转和双旋转:单旋转:只需旋转一次;双旋转:旋转两次;
- 左左情况:解决方法右旋
左节点插入元素后会造成高度差不符合AVL标准(左右子树高度差的绝对值不再 < 1)
解决方法:
-
右右情况:与左左类似,解决方法采用左旋
-
左右情况:解决方法左右旋,先左后右旋
左右旋:先左旋成左左情况,再右旋成正常情况
- 右左情况,和左右情况类似,解决方法为右左旋,先右旋再左旋
三. 多路查找树
多路查找树的每一个节点的孩子树可以多于两个,且每个节点处可以存储多个元素。多路查找树是一种特殊的查找树,所以其元素之间存在某种特定的排序关系。
3.1 2-3树
1.定义:
- 2-3树中每一个节点都具有两个孩子(我们称它为2节点)或三个孩子(我们称它为3节点)。
- 一个2节点包含一个元素和两个孩子(只能包含两个孩子或没有孩子,不能出现有一个孩子的情况),且与二叉排序树类似,左子树包含的元素小于该元素,右子树包含的元素大于该元素。
- 一个3节点包含一小一大两个元素和三个孩子(只能包含三个孩子或没有孩子,不能出现有一个孩子或有两个孩子的情况)。如果某个3节点有孩子,左子树包含小于较小元素的元素,右子树包含大于较大元素的元素,中间子树包含介于两元素之间的元素。
2.特点
- 优点:高度低,查询次数少
- 缺点:增加和删除的步骤繁琐
3.2-3树的插入实现
参考https://blog.csdn.net/disiwei1012/article/details/78900594?spm=1001.2014.3001.5501
插入之前,先要对2-3树进行一次未命中的查找
- 向2节点中插入节点
如果未命中查找结束于一个2节点,直接将2节点替换为一个3节点,并将要插入的键保存在其中。
- 向3节点中插入节点
1.父节点是2节点
以将新的元素插入到3-node节点中,使其成为一个临时的4-node节点,然后,将该节点中的中间元素提升到父节点即2-node节点中,使其父节点成为一个3-node节点,然后将左右节点分别挂在这个3-node节点的恰当位置。操作如下图:.
2.父节点是3节点
当我们插入的节点是3-node的时候,我们将该节点拆分,中间元素提升至父节点,但是此时父节点是一个3-node节点,插入之后,父节点变成了4-node节点,然后继续将中间元素提升至其父节点,直至遇到一个父节点是2-node节点,然后将其变为3-node,不需要继续进行拆分。
3.父节点到根节点均为3节点
父节点到根节点都是3节点的时候,这是如果我们要在字节点插入新的元素的时候,会一直查分到跟节点,在最后一步的时候,跟节点变成了一个4节点,这个时候,就需要将跟节点查分为两个2节点,树的高度加1,这个操作过程如下:
3.2 B树
1.定义
- B树又称为B-树,它是一种能够存储数据、对数据进行排序并允许以O(log n)的时间复杂度运行进行查找、顺序读取、插入和删除的数据结构。概括来说是一个节点可以拥有多于2个节点的二叉查找树。(降低深度)
- B树中的每个节点可以有两个以上的子节点,每个节点最多可以有m个孩子,其中m被称为B树的阶(order),每个节点最多可以存储m-1个用于比较的数据(key)
- B树根节点至少有两个节点;
- 每个中间节点(根节点和叶子节点除外)都包含k-1个元素和k个孩子节点,其中k的值大小在m/2和m之间
- 所有的叶子结点都位于同一层,每一个叶子节点都包含k-1个元素,其中k的值大小在m/2和m之间
- 每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划
-
特点:(高阶B树)
-
优点:当m越来越大的时候,B树就成了一个“又胖又矮”的小胖子了。这棵矮胖的树每个节点都存储了很多数据,每次取其中一个节点并使用二分查找,就能立马知道下一个节点的位置了,节点数量以及树的层数的降低使得I/O次数随之降低。
-
缺点:B树的节点是一个数据块,所以最坏的情况会浪费块内一半的空间,阶数m越大意味着空间浪费也越大。
3.3 B+树
B+树是对B树的一种变形树;通常B树的节点中同时存储了Key和Value,更准确的说应该是Value的引用(存储数据的物理地址)。我们比较的时候只需要Key而已,但是却把Value也取了出来,从而造成了不必要的I/O,虽然只是取出了value的引用,但是当数据库数据量越来越大的时候,对性能的影响也会随之累积而变得十分可观。
- 定义
- 非叶结点仅具有索引作用,跟记录有关的信息均存放在叶结点中。
- 所有的Value数据都保存在叶子节点中
- 叶子节点之间用指针串联起来
2.特点
- 所有的查找最终都会到叶子节点,从而保证了查询性能的稳定。
- 遍历方便,B+树的叶子结点都是相链的,因此对整棵树的遍历只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。
- 内部节点只存储key,节点会更小,意味着内存中可以缓存更多的节点。
四. 红黑树
红黑树也叫RB树,RB-Tree。是一种自平衡的二叉查找树,它的节点的颜色为红色和黑色。它不严格控制左、右子树高度或节点数之差小于等于1。
1.定义
- 节点是红色或黑色。
- 根节点是黑色。
- 每个叶子节点都是黑色的空节点(NIL节点)。
- 每个红色节点的两个子节点都是黑色。也就是说从每个叶子到根的所有路径上不能有两个连续的红色节点)。
- 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
2.特点(与AVL,BST比较)
- 红黑树在查找方面和AVL树操作几乎相同。但是在插入和删除操作上,AVL树每次插入删除会进行大量的平衡度计算,红黑树是牺牲了严格的高度平衡的优越条件为代价,它只要求部分地达到平衡要求,结合变色,降低了对旋转的要求,从而提高了性能。红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。
- 相比于BST,因为红黑树可以能确保树的最长路径不大于两倍的最短路径的长度,所以可以看出它的查找效果是有最低保证的。在最坏的情况下也可以保证O(logN)的,这是要好于二叉查找树的。因为二叉查找树最坏情况可以让查找达到O(N)。
- 红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高,所以在插入和删除中所做的后期维护操作肯定会比红黑树要耗时好多,但是他们的查找效率都是O(logN),所以红黑树应用还是高于AVL树的. 实际上插入 AVL 树和红黑树的速度取决于你所插入的数据.如果你的数据分布较好,则比较宜于采用 AVL树(例如随机产生系列数),但是如果你想处理比较杂乱的情况,则红黑树是比较快的。
3.应用
- 红黑树广泛用于TreeMap、TreeSet,以及jdk1.8后的HashMap(hash冲突链表超过8就转换成红黑树。