ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

红黑树

2022-05-04 17:02:18  阅读:153  来源: 互联网

标签:rightChild parent leftChild 红黑树 节点 left


从2-3-4树到红黑树:

  • 红黑树是对概念模型2-3-4树的一种实现,在二叉树的属性中加入一个颜色属性来表示2-3-4树中不同的节点。
  • 2-3-4树中的2节点对应着红黑树中的黑色节点,而2-3-4树中的非2节点是以红节点+黑节点的方式存在,红节点的意义是与黑色父节点结合,表达着2-3-4树中的3,4节点。
  • 2节点直接转化为黑色节点;3节点这里可以有两种表现形式,左倾红节点或者右倾红节点。而4节点被强制要求转化为一个黑父带着左右两个红色儿子。

红黑树其实就是对概念模型2-3树(或者2-3-4树)的一种实现

红黑规则:

  1. 节点不是红色就是黑色;
  2. 根节点是黑色;
  3. 红黑树的叶子节点并非传统的叶子节点,红黑树的叶子节点是null节点(空节点)且为黑色;
  4. 同一路径,不存在连续的红色节;
  5. 任意节点到叶子节点经过的黑色节点数目相同;
  • 约束4和5,保证了红黑树的大致平衡:根到叶子的所有路径中,最长路径不会超过最短路径的2倍。
  • 红黑树在最坏的情况下,查找复杂度也是O(log2N)。

左旋:

 

 1 public void leftRotate(RedBlackTreeNode p) {
 2     // 在当前节点不为null时,才进行左旋操作
 3     if (p != null) {
 4         // 先记录p的右儿子
 5         RedBlackTreeNode rightChild = p.right;
 6 
 7         // 1. 空出右儿子的左子树
 8         p.right = rightChild.left;
 9         // 左子树不为空,需要更新父节点
10         if (rightChild.left != null) {
11             rightChild.left.parent = p;
12         }
13 
14         // 2. 空出节点p的父节点
15         rightChild.parent = p.parent;
16         // 父节点指向右儿子
17         if (p.parent == null) { // 右儿子成为新的根节点
18             this.root = rightChild;
19         } else if (p == p.parent.left) { // 右儿子成为父节点的左儿子
20             p.parent.left = rightChild;
21         } else { // 右儿子成为父节点的右儿子
22             p.parent.right = rightChild;
23         }
24 
25         // 3. 右儿子和节点p成功会师,节点p成为左子树
26         rightChild.left = p;
27         p.parent = rightChild;
28     }
29 }

 

右旋:

 1 public void rightRotate(RedBlackTreeNode p) {
 2     if (p != null) {
 3         // 记录p的左儿子
 4         RedBlackTreeNode leftChild = p.left;
 5 
 6         // 1. 空出左儿子的右子树
 7         p.left = leftChild.right;
 8         // 右子树不为空,需要更新父节点
 9         if (leftChild.right != null) {
10             leftChild.right.parent = p;
11         }
12 
13         // 2. 空出节点p的父节点
14         leftChild.parent = p.parent;
15         // 父节点指向左儿子
16         if (p.parent == null) { // 左儿子成为整棵树根节点
17             this.root = leftChild;
18         } else if (p.parent.left == p) { // 左儿子成为父节点左儿子
19             p.parent.left = leftChild;
20         } else { // 左儿子成为父节点的右儿子
21             p.parent.right = leftChild;
22         }
23 
24         // 3. 顺利会师
25         leftChild.right = p;
26         p.parent = leftChild;
27     }
28 }

红黑树新增节点:

  • 新插入的节点默认为红色,原因:插入黑色节点会影响黑色高度,对红黑树的影响更大;
  • 新增节点x时,循环的依据: x != null && x != root && x.parent.color == RED,即节点非空、不是整棵树的根节点(保证存在父节点)且父节点为红色(违反红黑规则4,需要调整);
  • 完成循环调整后,需要将整棵树的根节点设为黑色,以满足红黑规则1;同时,根节点设为黑色,不会影响从根节点开始的所有路径的黑色高度。

删除节点:

  • 删除节点时,通过节点替换实现删除;
  • 假设替换节点为x,需要在x替换被删节点后,从x开始进行调整;
  • 调整操作,循环的依据: x != root && x.color == BLACK,即替换节点不能为整棵树的根节点,替换节点的颜色为黑色(改变了红黑高度);
  • 完成循环调整后,需要将x设为黑色,结束调整。

总结:

  • AVL是高度平衡的,频繁的插入和删除会引起频繁的rebalance,严重影响效率;
  • 红黑树其实是一种折中的做法,插入最多会引起两次旋转,删除最多会引起三次旋转;
  • 红黑树查找、插入、删除的复杂度都是O(logN)的,性能稳定, STL中set、map的底层实现都是红黑树。

标签:rightChild,parent,leftChild,红黑树,节点,left
来源: https://www.cnblogs.com/siu-miner/p/16221542.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有