Java面试相关-树

二叉排序树

或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有节点的值均小于它的根节点的值;
(2)若右子树不空,则右子树上所有节点的值均大于它的根节点的值;
(3)左、右子树也分别为二叉排序树。

Java面试相关-树_第1张图片

优点:相对于顺序查找来说,效率高了很多,提升了查询效率。

缺点:若二叉树极度不平衡,会导致查找效率大大降低。如下:

Java面试相关-树_第2张图片

为避免类似极端情况我们可以选择一种算法,将不平衡的二叉排序树转化为平衡二叉排序树。

平衡二叉搜索树(AVL树)

在符合二叉查找树的条件下,还满足任何节点的两个子树的高度最大差为 1.

如下图:

Java面试相关-树_第3张图片

红黑树(自平衡二叉查找树)

红黑树是每个节点带有颜色属性的二叉查找树,颜色或红或黑。在二叉查找树的强制要求以外,加入以下要求:

(1)节点是红色或者黑色。
(2)根节点是黑色节点。
(3)每个叶子节点都是黑色的空节点(NULL)
(4)每个红色节点的两个子节点都是黑色的(从根节点到叶子节点不存在连续两个红色的节点)。
(5)从任意节点到叶子节点所有路径中包含的黑色节点数目相同。

Java面试相关-树_第4张图片

当插入删除时,就会对平衡造成破坏,这时候需要对树进行调整,从而重新达到平衡。

红黑树补充知识点–左旋和右旋:

  1. 左旋

    Java面试相关-树_第5张图片

  2. 右旋

    Java面试相关-树_第6张图片

红黑树–插入(添加)节点:

首先将插入节点着色为红色,再插入二叉树将会产生三种情况:

情况①说明:被插入的节点是根节点。
处理方法:直接把此节点涂为黑色。

情况②说明:被插入的节点的父节点是黑色。
处理方法:什么也不需要做。节点被插入后,仍然是红黑树。

情况③说明:被插入的节点的父节点是红色。
处理方法:那么,该情况与红黑树的“特性(4)”相冲突。这种情况下,被插入节点是一定存在非空祖父节点的;进一步的讲,被插入节点也一定存在叔叔节点(即使叔叔节点为空,我们也视之为存在,空节点本身就是黑色节点)。理解这点之后,我们依据"叔叔节点的情况",将这种情况进一步划分为3种情况(Case)。

现象说明 处理策略
Case1 当前节点的父节点是红色,且当前节点的祖父节点的另一个子节点(叔叔节点)也是红色。 (01) 将“父节点”设为黑色。
(02) 将“叔叔节点”设为黑色。
(03) 将“祖父节点”设为“红色”。
(04) 将“祖父节点”设为“当前节点”(红色节点);即,之后继续对“当前节点”进行操作。
Case2 当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的右孩子 (01) 将“父节点”作为“新的当前节点”。
(02) 以“新的当前节点”为支点进行左旋。
Case3 当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的左孩子 (01) 将“父节点”设为“黑色”。
(02) 将“祖父节点”设为“红色”。
(03) 以“祖父节点”为支点进行右旋。

如下图:

  1. 插入新节点值为14(情况②):

Java面试相关-树_第7张图片

由于父节点15是黑色节点,所以此时没有破环结构,不需要做调整。

  1. 插入新节点值为21(情况③Case1):

    插入21节点:

Java面试相关-树_第8张图片

​ 符合情况③Case1,将父节点22和叔叔节点27变黑:
Java面试相关-树_第9张图片

​ 将祖父节点25设为红色,同时重置为插入节点,即现在插入节点为25:
Java面试相关-树_第10张图片

​ 此时新的节点25符合情况③Case2:

​ 将父节点17作为新的当前节点,进行左旋:
Java面试相关-树_第11张图片

参考:

红黑树的旋转与变色
红黑树(一)之 原理和算法详细介绍

平衡多路查找树(B-Tree)

B-Tree是为磁盘等外存储设备设计的一种平衡查找树。

为了描述B-Tree,首先定义一条数据记录为一个二元组[key, data],key为记录的键值,对于不同数据记录,key是互不相同的;data为数据记录除key外的数据。一棵m阶的B-Tree有如下特性:

  1. 每个结点至多可以拥有m个子结点。
  2. 除了根节点和叶子节点外,其它每个节点至少有(m/2)个孩子。
  3. 若根节点不是叶子节点,则至少有2个孩子
  4. 所有叶子节点都在同一层。
  5. 每个非终端节点包含n个key信息,(m/2)-1 <= n <= m-1
  6. 一个节点中的key从左到右升序排列。
  7. 每个指针要么为null,要么指向另外一个节点。
  8. 所有叶节点具有相同的深度,等于树高h。
  9. 如果某个指针在节点node最左边且不为null,则其指向节点的所有key小于v(key1),其中v(key1)为node的第一个key的值。
  10. 如果某个指针在节点node最右边且不为null,则其指向节点的所有key大于v(keym),其中v(keym)为node的最后一个key的值。
  11. 如果某个指针在节点node的左右相邻key分别是keyi和keyi+1且不为null,则其指向节点的所有key小于v(keyi+1)且大于v(keyi)。
  12. key和指针互相间隔,节点两端是指针。

如图为B-Tree:
Java面试相关-树_第12张图片

B+Tree

B+Tree是在B-Tree基础上的一种优化,常见的如MySQL就普遍使用B+Tree实现其索引结构。

在B-Tree数中可以看到每一个节点不仅包含数据的key值,还有data值,若data数据较大或存储数据量很大时性能会受影响。

而B+Tree中,所有数据记录节点都是按照键值大小顺序存放在同一层的叶子节点上,而非叶子节点上只存储key值信息,这样可以大大加大每个节点存储的key值数量,降低B+Tree的高度。

B+Tree相对B-Tree有几点不同:

  1. 非叶子节点只存储key信息。
  2. 数据记录都存放在叶子节点中。
  3. 所有叶子节点之间都有一个链指针。(针对经典B+Tree基础上进行了优化,增加了顺序访问指针)

Java面试相关-树_第13张图片

通常在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。

因此可以对B+Tree进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

参考

BTree和B+Tree详解
MySQL索引原理及BTree(B-/+Tree)结构详解

你可能感兴趣的:(面试备战)