学习杂记三:树

特征:

1)平衡二叉树(AVL树):

红黑树是在AVL树的基础上提出来的。

平衡二叉树又称为AVL树,是一种特殊的二叉排序树。其左右子树都是平衡二叉树,且左右子树高度之差的绝对值不超过1。

AVL树中所有结点为根的树的左右子树高度之差的绝对值不超过1。

将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF,那么平衡二叉树上的所有结点的平衡因子只可能是-1、0和1。只要二叉树上有一个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。

2)红黑树:

红黑树是在AVL树的基础上发展而来的。红黑树是一种二叉查找树,但在每个节点增加一个存储位表示节点的颜色,可以是红或黑(非红即黑)。通过对任何一条从根到叶子的路径上各个节点着色的方式的限制,红黑树确保没有一条路径会比其它路径长出两倍,因此,红黑树是一种弱平衡二叉树,相对于要求严格的AVL树来说,它的旋转次数少,所以对于搜索,插入,删除操作较多的情况下,通常使用红黑树。

3)红黑树较AVL树的优点:

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

所以红黑树在查找,插入删除的性能都是O(logn),且性能稳定,所以STL里面很多结构包括map底层实现都是使用的红黑树。

4)红黑树旋转:

旋转:红黑树的旋转是一种能保持二叉搜索树性质的搜索树局部操作。有左旋和右旋两种旋转,通过改变树中某些结点的颜色以及指针结构来保持对红黑树进行插入和删除操作后的红黑性质。

左旋:对某个结点x做左旋操作时,假设其右孩子为y而不是T.nil:以x到y的链为“支轴”进行。使y成为该子树新的根结点,x成为y的左孩子,y的左孩子成为x的右孩子。

右旋:对某个结点x做右旋操作时,假设其左孩子为y而不是T.nil:以x到y的链为“支轴”进行。使y成为该子树新的根结点,x成为y的右孩子,y的右孩子成为x的左孩子。

 

左旋

å·¦æ

右旋

å³æ


(来自金发只是水一下的博客:https://blog.csdn.net/qq_25940921/article/details/82183093
一、平衡二叉树

1、平衡二叉树的插入:

有四种插入情况:

①左左即为在原来平衡的二叉树上,在节点的左子树的左子树下,有新节点插入,导致节点的左右子树的高度差为2

   左左(通过节点右旋)恢复平衡

②右右即为在原来平衡的二叉树上,在节点的右子树的右子树下,有新节点插入,导致节点的左右子树的高度差为2

平衡äºåæ å³å³æåµè¿è¡å·¦æ
   右右(通过节点左旋)恢复平衡

③即为在原来平衡的二叉树上,在节点的左子树的右子树下,有新节点插入,导致节点的左右子树的高度差为2

  左右(通过左子树节点左旋,节点右旋)恢复平衡

④右左即为在原来平衡的二叉树上,在节点的右子树的左子树下,有新节点插入,导致节点的左右子树的高度差为2


                  

   右左(通过右子树节点右旋,节点左旋)恢复平衡

2、删除结点

删除二叉树节点总结起来就两个判断:①删除的是什么类型的节点?②删除了节点之后是否导致失衡?

节点的类型有三种:1.叶子节点;2.只有左子树或只有右子树;3.既有左子树又有右子树。

针对这三种节点类型,再引入判断②,所以处理思路分别是:

(1)当删除的节点是叶子节点,则将节点删除,然后从父节点开始,判断是否失衡,如果没有失衡,则再判断父节点的父节点是否失衡,直到根节点,此时到根节点还发现没有失衡,则说此时树是平衡的;如果中间过程发现失衡,则判断属于哪种类型的失衡(左左,左右,右左,右右),然后进行调整。

(2)删除的节点只有左子树或只有右子树,这种情况其实就比删除叶子节点的步骤多一步,就是将节点删除,然后把仅有一支的左子树或右子树替代原有结点的位置,后面的步骤就一样了,从父节点开始,判断是否失衡,如果没有失衡,则再判断父节点的父节点是否失衡,直到根节点,如果中间过程发现失衡,则根据失衡的类型进行调整。

(3)删除的节点既有左子树又有右子树,这种情况又比上面这种多一步,就是中序遍历,找到待删除节点的前驱或者后驱都行,然后与待删除节点互换位置,然后把待删除的节点删掉,后面的步骤也是一样,判断是否失衡,然后根据失衡类型进行调整。
 

二、2-3-4树

1、2-3-4树的插入

(依然来自金发只是水一下的博客:https://blog.csdn.net/qq_25940921/article/details/82183601

2-3-4树只是在2-3树的基础上进行了扩展。2-3-4树也是一棵自平衡的多路查找树,具有如下性质:

(1)任一节点只能是1个或2个或3个key,对应的子节点为2个子节点或3个子节点或4个子节点;

(2)所有叶子节点到根节点的长度一致;

(3)每个节点的key从左到右保持了从小到大的顺序,两个key之间的子树中所有的key一定大于它的父节点的左key,小于父节点的右key,对于3个key的节点,两两key之间也是如此。

(1)如果待插入的节点不是3个key,则直接插入即可;

(2)如果待插入的节点有3个key,则对节点进行分裂,即3个key加上待插入的key,这4个key分裂成1个key跟2个子节点,然后将分裂之后的4个key中的父节点看作向上层插入的key,然后重复(1)、(2)步骤,直到满足2-3-4树的定义性质。

如下图所示,插入“125”,而此时待插入节点有3个key,需要对节点进行分裂

 

 

2-3-4æ æå¥æåµï¼2ï¼-3

 

三、红黑树

1、红黑树的插入

     红黑树的概念:(依然来自金发只是水一下的博客:https://blog.csdn.net/qq_25940921/article/details/82184055

(1)节点是红色或黑色;

(2)根节点是黑色;

(3)每个叶节点(NIL节点,空节点)是黑色的;

(4)从每个叶子到根的所有路径上不能有两个连续的红色节点;

(5)从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

 关于红黑树的节点插入,首先,新节点直接插入并初始化颜色为红色

因为要满足红黑树的五条性质,如果我们插入的是黑色节点,直接违反了性质(5),红黑树肯定需要进行调整,但是如果我们插入的是红色节点,不一定需要对树进行调整(父节点是黑色时,不需要调整,只有当其父节点是红色时,才需要调整)所以,我们把要插入的节点的颜色变成红色。

判断:

 

(1)若新插入节点是根节点,违反了性质(2),则将节点颜色改为黑色即可;

(2)若新插入节点的父节点为黑色,此时无需调整,满足红黑树;

(3)若新插入节点的父节点为红色,违反了性质(4),此时需要对树进行调整,出现调整的场景大体上为两种,即父节点的兄弟节点–叔父节点,是黑色的NIL节点或者为红色节点。如下图所示。另外,具体细分下去还有红父节点是祖父节点的左孩子还是右孩子,插入节点是红父节点的左孩子还是右孩子,下面会逐一分析。

a.若新插入节点的叔父节点为红色,如上的右图,此时只需将祖父节点(“30”)改为红色,然后将父节点(“50”)与叔父节点(“22”)都改为红色即可,最后将祖父节点(红色“30”)看作向上层新插入的当前节点,重复(1)(2)(3)的判断,直到满足红黑树。实际上这种场景无论新插入节点为父节点的左孩子还是右孩子,父节点是祖父节点的左孩子还是有孩子,都是这样调整,即只需修改颜色,无需旋转变换,如下图。

按照判断(1),将根节点变为黑色

b.若新插入节点的叔父节点为黑色NIL节点,则存在插入节点是父节点的左孩子还是右孩子,父节点是祖父节点的左孩子还是右孩子,4 种情况,如下:

i.父节点为祖父节点的左孩子,插入节点为父节点的左孩子,如下图,调整只需对祖父节点右旋,然后将右旋后的父节点涂黑,左右子节点涂红即可,此时满足红黑树。

 ii.父节点为祖父节点的左孩子,插入节点为父节点的右孩子,如下图,调整比上面的 i 多一步,即将先对父节点左旋,变成 i 的情况,然后后面跟 i 一样,对祖父节点进行右旋,然后将右旋后的父节点涂黑,左右子节点涂红,此时满足红黑树。

iii.父节点为祖父节点的右孩子,插入节点为父节点的右孩子,如下图,实际上情况 iii 与情况 i 互为镜像,调整只需对祖父节点左旋,然后将左旋后的父节点涂黑,左右子节点涂红即可,此时满足红黑树。

iv.父节点为祖父节点的右孩子,插入节点为父节点的左孩子,如下图,调整比上面的 iii 多一步,即将先对父节点右旋,变成 iii 的情况,然后后面跟 iii 一样,对祖父节点进行左旋,然后将左旋后的父节点涂黑,左右子节点涂红,此时满足红黑树。实际上情况 iv 与情况 ii 互为镜像。

 

平衡二叉树,2-3-4树,红黑树的删除操作:

2-3-4树删除,和其他树删除类似:
删除的节点是非叶子节点,无论待删除节点的key是多少个,先使用中序遍历找到待删除节点的后继节点,然后将后继节点与待删除节点位置互换,此时就将问题转化为删除节点为叶子节点

红黑树与2-3-4树之间是可以互相转化的,如果一棵树满足红黑树,把红色的节点收缩到其父节点 ,就变成了2-3-4树,所有红色节点都与其父节点构成2个key或3个key的节点,其它节点为1个key的节点。如下图,

红黑树与2-3-4树的相互转化

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值