回顾Java基础——二叉树和红黑树

二叉树

二叉树是树的特殊一种,具有如下特点:
1、每个结点最多有两颗子树,结点的度最大为2。
2、左子树和右子树是有顺序的,次序不能颠倒。
3、即使某结点只有一个子树,也要区分左右子树。

一、特殊的二叉树及特点

1、斜树

所有的结点都只有左子树(左斜树),或者只有右子树(右斜树)。这就是斜树,应用较少

在这里插入图片描述

2、满二叉树

所有的分支结点都存在左子树和右子树,并且所有的叶子结点都在同一层上,这样就是满二叉树。就是完美圆满的意思,关键在于树的平衡。

在这里插入图片描述

根据满二叉树的定义,得到其特点为:

叶子只能出现在最下一层。
非叶子结点度一定是2.
在同样深度的二叉树中,满二叉树的结点个数最多,叶子树最多。

3、完全二叉树

对一棵具有n个结点的二叉树按层序排号,如果编号为i的结点与同样深度的满二叉树编号为i结点在二叉树中位置完全相同,就是完全二叉树。满二叉树必须是完全二叉树,反过来不一定成立。

其中关键点是按层序编号,然后对应查找。

在这里插入图片描述

在上图中,树1,按层次编号5结点没有左子树,有右子树,10结点缺失。树2由于3结点没有字数,是的6,7位置空挡了。树3中结点5没有子树。

在这里插入图片描述

上图就是一个完全二叉树。

结合完全二叉树定义得到其特点:

叶子结点只能出现在最下一层(满二叉树继承而来)
最下层叶子结点一定集中在左 部连续位置。
倒数第二层,如有叶子节点,一定出现在右部连续位置。
同样结点树的二叉树,完全二叉树的深度最小(满二叉树也是对的)。

红黑树

通过颜色的约束,红黑树维持着二叉搜索树的平衡性。一颗红黑树必须满足以下几点条件:

规则1、根节点必须是黑色。

规则2、任意从根到叶子的路径不包含连续的红色节点。

规则3、任意从根到叶子的路径的黑色节点总数相同。

如图所示,为一颗合法的红黑树,可以发现红黑树在维持二叉搜索树的基本性质的前提下,并满足了红黑树的颜色条件,整体上保持了二叉搜索树的平衡性。

在这里插入图片描述

红黑树的插入操作:

红黑树的插入操作和查询操作有些类似,它按照二分搜索的方式递归寻找插入点。
不过这里需要考虑边界条件——当树为空时需要特殊处理(这里未采用STL对树根节点实现的特殊技巧)。
如果插入第一个节点,我们直接用树根记录这个节点,并设置为黑色,否则作递归查找插入(__insert操作)。

默认插入的节点颜色都是红色,因为插入黑色节点会破坏根路径上的黑色节点总数,但即使如此,也会出现连续红色节点的情况。
因此在一般的插入操作之后,出现红黑树约束条件不满足的情况(称为失去平衡)时,就必须要根据当前的红黑树的情况做相应的调整(__rebalance操作)。
和AVL树的平衡调整通过旋转操作的实现类似,红黑树的调整操作一般都是通过旋转结合节点的变色操作来完成的。

红黑树插入节点操作产生的不平衡来源于当前插入点和父节点的颜色冲突导致的(都是红色,违反规则2)。

在这里插入图片描述

如图所示,由于节点插入之前红黑树是平衡的,
因此可以断定祖父节点g必存在(规则1:根节点必须是黑色),
且是黑色(规则2:不会有连续的红色节点),而叔父节点u颜色不确定,因此可以把问题分为两大类:

1、叔父节点是黑色(若是空节点则默认为黑色)

这种情况下通过旋转和变色操作可以使红黑树恢复平衡。
但是考虑当前节点n和父节点p的位置又分为四种情况:

A、n是p左子节点,p是g的左子节点。

B、n是p右子节点,p是g的右子节点。

C、n是p左子节点,p是g的右子节点。

D、n是p右子节点,p是g的左子节点。

情况A,B统一称为外侧插入,C,D统一称为内侧插入。
之所以这样分类是因为同类的插入方式的解决方式是对称的,可以通过镜像的方法相似完成。

首先考虑情况A:n是p左子节点,p是g的左子节点。
针对该情况可以通过一次右旋转操作,并将p设为黑色,g设为红色完成重新平衡。

在这里插入图片描述

右旋操作的步骤是:将p挂接在g节点原来的位置(如果g原是根节点,需要考虑边界条件),
将p的右子树x挂到g的左子节点,再把g挂在p的右子节点上,完成右旋操作。
这里将最终旋转结果的子树的根节点作为旋转轴(p节点),
也就是说旋转轴在旋转结束后称为新子树的根节点!
这里需要强调一下和STL的旋转操作的区别,STL的右旋操作的旋转轴视为旋转之前的子树根节点
(g节点),不过这并不影响旋转操作的效果。

类比之下,情况B则需要使用左单旋操作来解决平衡问题,方法和情况A类似。

在这里插入图片描述

总结:

一、原理

我的理解:

链表查找元素,速度受链表长度影响太大,所以按照二分法思想,就产生了二叉树。

所谓的二分法,就是选一个基准,按基准来判断大于或者小于此基准,然后一次可以缩小
一半的范围,然后在选择的范围中,再次重复此过程.

二叉树的特点就是
左边子节点比根节点小
右边子节点比根节点大

二叉树查找有先序、中序、后序,
分别对应 根左右、左根右、左右根,中序是可以保证遍历出来是顺序是从小到大的。

二叉树:

1、满二叉树:
就是叶子节点(最后一层)是最大的节点数量
2、完全二叉树:
除了叶子节点,其它层的节点数量,左右都是一样的。

二叉树不稳定性:
因为要保证左小于根,右大于根,所以可能数据在插入后会退化成这样:
在这里插入图片描述

如果在这个树里面查找一个数据,基本上就退化成为链表了。

红黑树:
就是为了解决上面的问题而来,是一种自动平衡的二叉查找树。

特性:

   1、每个节点都有红色或黑色
   2、树的根始终是黑色的 
   3、没有两个相邻的红色节点
   4、从节点(包括根)到其任何后代NULL节点(就是叶子结点下方挂的两个空节点),
  的每条路径都具有相同数量的黑色节点。
  说白了,就是每层每个子二叉树不可能出现一黑一红的情况。

	基于以上特性,当我们插入的数破坏二叉树平衡之后,会根据左旋、右旋、
	变颜色来自动平衡回来。

自平衡步骤:

1、首先所有插入的数据,一开始都是红节点。

2、变颜色的条件:

(1)、根节点必须变为黑色
(2)、父节点和叔叔节点都为红色

这种情况下,会将父节点和叔叔节点变为黑色,祖父节点设置为红色。
当操作指针,变为祖父节点。

3、左旋条件:

父红叔黑,并且当前节点是右子树。就以父节点左旋。
实际上就是父节点上移,祖父节点走到左下,
父节点的左子节点移到原祖父节点的右子节点上。

4、右旋条件:

父红叔黑,并且当前节点是左子树。就以祖父节点右旋。
实际上就是祖父节点下移,父节点上移,
父节点的右子节点移动到原祖父节点的左子节点

移动之后还需要:
父节点变为黑色,祖父节点变成红色。


经过这一系列的左旋、右旋、变色之后,红黑树可以达到平衡状态,
然后去查询数据,就会快很多。这也是红黑树存在的目的。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值