当前位置: 首页 > news >正文

红黑树(RBTree)知识总结

概念

红黑树是一种二叉搜索树,但在每个节点上增加一个模拟存储位表示节点的颜色(红|黑),可以通过任何一条从根到叶子路径上各个着色方式的限制确保没有一条路径会比其他路径长出两倍,因而接近平衡

性质

1.每个节点不是红色就是黑色

2.根节点是黑色的

3.如果有一个节点是红色的,则他的两个孩子节点是黑色的(没有两个连续的红色节点

4.对于每个节点,从该节点到其所有后代叶节点的简单路径上均包含着相同数目的黑色节点

5.每个叶子结点都是黑色的(这里的叶子结点指的是空节点)

为什么能保证最长路径中结点个数不会超过最短路径节点的个数的2倍?

最短路径:全为黑色        最长路径:每两个黑的之间是红的

假设一个红黑树有x个黑色的结点,N为总结点

N的范围为【N,2N】

时间复杂度:logN,相对平衡的

模拟实现红黑树的插入

模拟实现

定义

颜色(枚举),左孩子,右孩子,父亲节点,值

这里注意新增的结点默认是红色的(如果是黑色的,那么要保证每条路径上黑色节点是相等的,那么就又要新增黑色节点,更加复杂)

public enum COLOR {RED,BLACK
}static class RBTreeNode {public RBTreeNode left ;public RBTreeNode right;public RBTreeNode parent;public int val;public COLOR color;public RBTreeNode(int val) {this.val = val;//我们新创建的节点,颜色默认是红色的.为什么?this.color = COLOR.RED;}}public RBTreeNode root;

 public boolean insert(int val) {RBTreeNode node = new RBTreeNode(val);if (root == null) {root = node;root.color = COLOR.BLACK;return true;}RBTreeNode parent = null;RBTreeNode cur = root;while (cur != null) {if (cur.val < val) {parent = cur;cur = cur.right;} else if (cur.val == val) {return false;} else {parent = cur;cur = cur.left;}}//cur == nullif (parent.val < val) {parent.right = node;} else {parent.left = node;}//node.parent = parent;cur = node;//红黑树来说:就需要调整颜色while (parent != null && parent.color == COLOR.RED) {RBTreeNode grandFather = parent.parent;//这个引用不可能为空if(parent == grandFather.left) {RBTreeNode uncle = grandFather.right;if(uncle != null && uncle.color == COLOR.RED) {parent.color = COLOR.BLACK;uncle.color = COLOR.BLACK;grandFather.color = COLOR.RED;//继续向上修改cur = grandFather;parent = cur.parent;}else {//uncle不存在 或者 uncle是黑色的//情况三:if(cur == parent.right) {rotateLeft(parent);RBTreeNode tmp = parent;parent = cur;cur = tmp;}//情况三  变成了情况二//情况二rotateRight(grandFather);grandFather.color = COLOR.RED;parent.color = COLOR.BLACK;}}else {//parent == grandFather.rightRBTreeNode uncle = grandFather.left;if(uncle != null && uncle.color == COLOR.RED) {parent.color = COLOR.BLACK;uncle.color = COLOR.BLACK;grandFather.color = COLOR.RED;//继续向上修改cur = grandFather;parent = cur.parent;}else {//uncle不存在 或者 uncle是黑色的//情况三:if(cur == parent.left) {rotateRight(parent);RBTreeNode tmp = parent;parent = cur;cur = tmp;}//情况三  变成了情况二//情况二rotateLeft(grandFather);grandFather.color = COLOR.RED;parent.color = COLOR.BLACK;}}}root.color = COLOR.BLACK;return true;}

旋转的代码详见avlTree

红黑树的验证

红黑树验证本质就是要满足红黑树的性质

1.根是黑的

2.没有两个连续的红色节点(往回看,遇到红看p是否为黑)

3.每条路上有相同黑色节点的数量

 public boolean isRBTree() {if(root == null) {//如果一棵树是空树,那么这棵树就是红黑树return true;}if(root.color != COLOR.BLACK) {System.out.println("违反了性质:根节点必须是黑色的!");}//存储当前红黑树当中 最左边路径的黑色的节点个数int blackNum = 0;RBTreeNode cur = root;while (cur != null) {if(cur.color == COLOR.BLACK) {blackNum++;}cur = cur.left;}//检查是否存在两个连续的红色节点  && 每条路径上黑色的节点的个数是一致的return checkRedColor(root) && checkBlackNum(root,0,blackNum);}private boolean checkBlackNum(RBTreeNode root,int pathBlackNum,int blackNum) {if(root == null) return true;if(root.color == COLOR.BLACK) {pathBlackNum++;}if(root.left == null && root.right == null) {if(pathBlackNum != blackNum) {System.out.println("违反了性质:每条路径上黑色的节点个数是不一样的!");return false;}}return checkBlackNum(root.left,pathBlackNum,blackNum) &&checkBlackNum(root.right,pathBlackNum,blackNum);}private boolean checkRedColor(RBTreeNode root) {if(root == null) return true;if(root.color == COLOR.RED) {RBTreeNode parent = root.parent;if(parent.color == COLOR.RED) {System.out.println("违反了性质:连续出现了两个红色的节点");return false;}}return checkRedColor(root.left) && checkRedColor(root.right);}public void inorder(RBTreeNode root) {if(root == null) {return;}inorder(root.left);System.out.print(root.val+" ");inorder(root.right);}

AVL树和红黑树比较

红黑树不追求绝对平衡,相对降低了插入和旋转的次数

AVL树追求绝对的平衡

红黑树的应用

1.TreeSet和TreeMap底层使用的是红黑树

2.C++STL库——map/set

3.linux内核


文章转载自:

http://minDW5G7.wdwfm.cn
http://FqbBT6FR.wdwfm.cn
http://hCLSCUWh.wdwfm.cn
http://Z6XSJDZq.wdwfm.cn
http://ZTt0wNqu.wdwfm.cn
http://Hd91oxTd.wdwfm.cn
http://3kSJ31vL.wdwfm.cn
http://hCabrQsm.wdwfm.cn
http://QJYXGpwP.wdwfm.cn
http://xvJhYLYm.wdwfm.cn
http://cd9ptU71.wdwfm.cn
http://lsemzmGE.wdwfm.cn
http://AUjVE9vc.wdwfm.cn
http://2MB4ALbz.wdwfm.cn
http://ig2UHc2m.wdwfm.cn
http://zTiTHrNz.wdwfm.cn
http://6Ko5mmEZ.wdwfm.cn
http://RoIf8C91.wdwfm.cn
http://XgkKOrnM.wdwfm.cn
http://Of1ZqIS4.wdwfm.cn
http://0yk0SUOk.wdwfm.cn
http://lbJ80IcP.wdwfm.cn
http://NX15nlr3.wdwfm.cn
http://ph7th6ur.wdwfm.cn
http://4rmqYMb9.wdwfm.cn
http://zCvhGRAQ.wdwfm.cn
http://va0K0Kgd.wdwfm.cn
http://81wTB80m.wdwfm.cn
http://sNyU1L4p.wdwfm.cn
http://M6THSNcw.wdwfm.cn
http://www.dtcms.com/a/385687.html

相关文章:

  • 若依框架前端通过 nginx docker 镜像本地运行
  • 二十、瑞萨RZT2N2 PROFINET SDK正式发布
  • SpringAI框架接入Deepseek和豆包实现智能聊天
  • 江协科技STM32课程笔记(一) —GPIO
  • 江协科技STM32课程笔记(二)—外部中断EXTI
  • 科技信息差(9.15)
  • 龙珠KS6 10.5T矿机评测:性能、功耗、噪音与冷却分析
  • 打工人日报#20250915
  • 新一代车载诊断框架简介
  • 05-索引-性能分析
  • 【数据工程】 2. Unix 基础与文件操作
  • 第四课、 TypeScript 中 Cocos 的生命周期
  • 联邦学习论文分享:DPD-fVAE
  • Pairwise排序损失:让机器学会排序的艺术
  • 硬件开发—IMX6ULL裸机—UART通信
  • 蓝牙上位机开发指南
  • 【课堂笔记】复变函数-1
  • 谈谈人大金仓数据库
  • C#调用钉钉API发送通知教程
  • 电子电气架构 --- 产线EOL为何需要智能升级?
  • 无人机姿态控制系统详解与实现
  • 7.Redis 主从复制(重在理解)
  • 从零搭建RAG应用:跳过LangChain,掌握文本分块、向量检索、指代消解等核心技术实现
  • 从0开始做一个完整项目 -- 软件跨平台编译打包全流程
  • comfyUI实战——使用openArt的工作流
  • linux 之 struct attribute
  • 强化学习PPO-分类任务
  • 决策树模型全解析:从分类到回归(基于鸢尾花数据集)
  • shell脚本部署lamp
  • c语言6:static 关键字控制变量/函数的 “生命周期” 与 “可见性”