前言: 最近在面试时,突然被问了关于树的问题,一下就将我脑瓜子搞的有点懵懵的!当时在大脑里游荡两个B,一个B树、一个B+树的关键字,但具体是怎么样的就不知道啦!今天就探讨一下树到底有多少类数据结构与底层如何实现及其有什么作用?
树的类型
无序树、有序树、二叉树、满二叉树、完全二叉树、二叉查找树(二叉排序树/搜索树)、树堆、平衡二叉树(AVL)、红黑树、B树、B+树、B*树、哈夫曼树
-
无序树: 一个父节点下的子节点没有顺序关系,称为无序树,也是自由树。
-
有序树: 一个父节点下的子节点有严格的顺序关系,称为有序树。
-
二叉树:树的任意节点至多包含两棵子树。
-
满二叉树:叶子节点都在同一层并且除叶子节点外的所有节点都有两个子节点。
-
完全二叉树: 对于一颗二叉树,假设其深度为d(d>1)。除第d层外的所有节点构成满二叉树,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树。
-
二叉查找树:
- 若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;
- 若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;
- 任意节点的左、右子树也分别为二叉查找树;
- 没有键值相等的节点。
-
树堆:树堆(Treap)是二叉排序树(Binary Sort Tree)与堆(Heap)结合产生的一种拥有堆性质的二叉排序树。
-
平衡二叉树(AVL): 它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,同时,平衡二叉树必定是二叉搜索树。
-
红黑树:一种被赋予颜色含义的平衡二叉树。
-
B树:B 树是一种平衡的多分树。
-
B+树:m阶B+树是m阶B-tree的变体,它的定义大致跟B-tree一致。
-
B*树:B*树是B+树的变体。
-
哈夫曼树: 哈夫曼树是一种针对权值的二叉树。一般为了减少计算机运算速度,将权重大的放在最前面。
二叉树
二叉树特点:
-
- 每个结点最多有两棵子树,即二叉树不存在度大于2的结点。
-
- 二叉树的子树有左右之分,其子树的次序不能颠倒。
如图所示:
- 二叉树的子树有左右之分,其子树的次序不能颠倒。
如图所示:
二叉树前序遍历、中序遍历、后序遍历
(1)先序遍历
先序遍历可以想象为,一个小人从一棵二叉树根节点为起点,沿着二叉树外沿,逆时针走一圈回到根节点,路上遇到的元素顺序,就是先序遍历的结果
先序遍历结果为:A B D H I E J C F K G
(2)中序遍历
中序遍历可以看成,二叉树每个节点,垂直方向投影下来(可以理解为每个节点从最左边开始垂直掉到地上),然后从左往右数,得出的结果便是中序遍历的结果
中遍历结果为:H D I B E J A F K C G
(3)后序遍历
后序遍历就像是剪葡萄,我们要把一串葡萄剪成一颗一颗的。 还记得我上面提到先序遍历绕圈的路线么?(不记得翻上面理解) 就是围着树的外围绕一圈,如果发现一剪刀就能剪下的葡萄(必须是一颗葡萄)(也就是葡萄要一个一个掉下来,不能一口气掉超过1个这样),就把它剪下来,组成的就是后序遍历了。 后序遍历中,根节点默认最后面
后序遍历结果:H I D J E B K F G C A
参考资料链接:二叉树的多种遍历
满二叉树
一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是(2^k) -1 ,则它就是满二叉树。
如图所示:
完全二叉树
完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
如图所示:
二叉查找树
二叉查找树,也称二叉搜索树,或二叉排序树。其定义也比较简单,要么是一颗空树,要么就是具有如下性质的二叉树:
- 1.若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 2.若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 3.任意节点的左、右子树也分别为二叉查找树;
- 4.没有键值相等的节点
--
平衡二叉树(AVL)
平衡二叉树、红黑树、B树、B+树数据结构比较深,通过文字描述很难理解,推荐在B站上观看视频学习,下面只是做了简单的梳理,如果没有学习过B树、B+树的话,再次推荐观看视频学习。
二叉排序树有一个不足的地方,就是如果插入的结点的值的顺序,是越来越小或者越来越大的,那么BST就会退化为一条链表,那么其查询的时间复杂度就会降为O(n)。如下图所示:
平衡二叉树是基于二叉查找树优化而来的。它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树,同时,平衡二叉树必定是二叉搜索树。常用算法有红黑树、AVL、Treap、伸展树等。在平衡二叉搜索树中,我们可以看到,其高度一般都良好地维持在O(log(n)),大大降低了操作的时间复杂度。
-
- 是「二叉排序树」
-
- 任何一个节点的左子树或者右子树都是「平衡二叉树」(左右高度差小于等于 1)
参考链接:平衡二叉树
红黑树
红黑树的英文是“Red-Black Tree”,简称 R-B Tree,它是一种不严格的平衡二叉查找树
红黑树中的节点,一类被标记为黑色,一类被标记为红色。除此之外,一棵红黑树还需要满足这样几个要求:
- 根节点是黑色的;
- 每个叶子节点都是黑色的空节点(NIL),也就是说,叶子节点不存储数据(图中将黑色的、空的叶子节点都省略掉了);
- 任何相邻的节点都不能同时为红色,也就是说,红色节点是被黑色节点隔开的;
- 每个节点,从该节点到达其可达叶子节点的所有路径,都包含相同数目的黑色节点;
参考链接:张彦峰ZYF
B树
B树的出现是为了弥合不同的存储级别之间的访问速度上的巨大差异,实现高效的 I/O。平衡二叉树的查找效率是非常高的,并可以通过降低树的深度来提高查找的效率。但是当数据量非常大,树的存储的元素数量是有限的,这样会导致二叉查找树结构由于树的深度过大而造成磁盘I/O读写过于频繁,进而导致查询效率低下。另外数据量过大会导致内存空间不够容纳平衡二叉树所有结点的情况。B树又名平衡多路查找树,即一个结点的查找路径不止左、右两个,而是有多个。数据库索引技术里大量使用者B树和B+树的数据结构。
B树的阶数:M阶表示 一个B树的结最多有多少个查找路径(即这个结点有多少个子节点)。M=M路,M=2是二叉树,M=3则是三叉树。
一棵M阶B树有以下特点:
-
- 每个结点的值(索引) 都是按递增次序排列存放的,并遵循左小右大原则。
-
- 根结点 的 子节点 个数为 [2,M]。
-
- 除 根结点 以外 的 非叶子结点 的子节点个数 为[ Math.ceil(M/2),M]。
-
- 每个 非叶子结点 的值(索引) 个数 = 子节点个数 -1 。最小为 Math.ceil(M/2)-1 最大为 M-1 个。
-
- B树的所有叶子结点都位于同一层。
参考链接:B树与B+树
B+树
B+树是B树的一种变形,它更适合实际应用中操作系统的文件索引和数据库索引。定义如下:(这里使用阶数 m来定义B+树)
- 除根节点外的内部节点,每个节点最多有m个关键字,最少有 m/2个关键字。其中每个关键字对应一个子树(也就是最多有m棵子树,最少有m/2棵子树);
- 根节点要么没有子树,要么至少有2棵子树;
- 所有的叶子节点包含了全部的关键字以及这些关键字指向文件的指针
- 所有叶子节点中的关键字按大小顺序排列
- 相邻的叶子节点顺序链接(相当于是构成了一个顺序链表)
- 所有叶子节点在同一层
- 所有分支节点的关键字都是对应子树中关键字的最大值
参考链接:B树与B+树
哈夫曼树
哈夫曼树(Huffman Tree)是在叶子结点和权重确定的情况下,带权路径长度最小的二叉树,也被称为最优二叉树。
参考链接: 哈夫曼树