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

红黑树详解初版


一、红黑树核心性质

红黑树是自平衡二叉搜索树,需满足5条性质:

  1. 节点非红即黑
  2. 根节点必须为黑
  3. 叶子节点(NIL)均为黑
  4. 红色节点子节点必为黑(无连续红节点)
  5. 任意节点到叶子路径的黑节点数相同(黑高度一致)

二、C++节点结构定义

enum Colour { RED, BLACK };template <typename K, typename V>
struct RBTreeNode {K key;V value;Colour color;RBTreeNode *left, *right, *parent;RBTreeNode(K k, V v) : key(k), value(v), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}
};

节点默认红色以最小化插入调整代价


三、插入操作详解

步骤1:二叉搜索树插入
bool Insert(const pair<K, V>& kv) {if (!root) { root = new Node(kv, BLACK); return true; }// 查找插入位置(同普通BST)//...// 新节点插入为红色cur = new Node(kv);cur->color = RED;parent->left/right = cur;cur->parent = parent;// 进入调整逻辑FixInsert(cur);
}
步骤2:插入后调整(FixInsert)
情况1:叔节点为红
祖父节点-黑
父节点-红
叔节点-红
新节点-红

处理方案
父、叔变黑,祖父变红,递归处理祖父节点

parent->color = uncle->color = BLACK;
grandfather->color = RED;
cur = grandfather; // 向上递归
情况2:叔节点为黑(直线型)
祖父
父-红
新节点-红
叔-黑

处理方案
祖父右旋,父变黑,祖父变红

RotateR(grandfather);
parent->color = BLACK;
grandfather->color = RED;
情况3:叔节点为黑(折线型)
祖父
父-红
新节点-红
NULL

处理方案
先左旋父节点转换为直线型,再按情况2处理

RotateL(parent);
RotateR(grandfather);

四、删除操作核心逻辑

步骤1:BST标准删除
void Delete(K key) {Node* target = Search(key);if (!target) return;// 处理单子节点/叶子节点删除//...// 若删除黑色节点需进入双黑修正if (target->color == BLACK) FixDoubleBlack(replacement);
}
步骤2:双黑修正(FixDoubleBlack)
情况1:兄弟节点为红
父-黑
兄-红
当前节点-黑
左子-黑
右子-黑

处理方案
父节点左旋,兄弟变黑,父变红

RotateL(parent);
sibling->color = BLACK;
parent->color = RED;
情况2:兄弟节点为黑且远侄子为红
父-红
兄-黑
远侄子-红

处理方案
父节点左旋,远侄子变黑,父继承原父颜色

RotateL(parent);
sibling->right->color = BLACK;
parent->color = original_color;

五、旋转操作代码实现

左旋示例:
左旋前结构
左旋后结构
左指针
右指针
右指针
右指针
左指针
右指针
父节点P
当前节点X
右子节点Y
Y的左子树α
Y的右子树β
当前节点X
新父节点Y
原父节点P
α子树
β子树

关键步骤解析​:

  1. 原父节点P的右子节点Y上升为新父节点
  2. 将Y的左子树α挂载到X的右子树
  3. 原父节点P的右指针指向Y
  4. Y的左指针指向X(形成父子关系反转)
void RotateL(Node* x) {Node* y = x->right;x->right = y->left;if (y->left) y->left->parent = x;y->parent = x->parent;if (!x->parent) root = y;else if (x == x->parent->left) x->parent->left = y;else x->parent->right = y;y->left = x;x->parent = y;
}

右旋对称实现


六、示例

10
20
30
40
50
60
70

七、完整代码

#include <iostream>
using namespace std;enum Colour { RED, BLACK };template<class K, class V>
struct RBTreeNode {pair<K, V> _kv;Colour _col;RBTreeNode<K, V>* _left;RBTreeNode<K, V>* _right;RBTreeNode<K, V>* _parent;RBTreeNode(const pair<K, V>& kv): _kv(kv),_col(RED),_left(nullptr),_right(nullptr),_parent(nullptr) {}
};template<class K, class V>
class RBTree {typedef RBTreeNode<K, V> Node;
public:RBTree() {NIL = new Node(make_pair(K(), V()));NIL->_col = BLACK;_root = NIL;}bool Insert(const pair<K, V>& kv) {if (_root == NIL) {_root = new Node(kv);_root->_col = BLACK;_root->_left = _root->_right = NIL;return true;}Node* parent = NIL;Node* cur = _root;while (cur != NIL) {parent = cur;if (cur->_kv.first > kv.first)cur = cur->_left;else if (cur->_kv.first < kv.first)cur = cur->_right;elsereturn false;}Node* newNode = new Node(kv);newNode->_left = newNode->_right = NIL;if (parent->_kv.first > kv.first)parent->_left = newNode;elseparent->_right = newNode;newNode->_parent = parent;FixInsert(newNode);return true;}private:Node* _root;Node* NIL; // 哨兵节点[2,4]// 左旋修正void RotateL(Node* x) {Node* y = x->_right;x->_right = y->_left;if (y->_left != NIL)y->_left->_parent = x;y->_parent = x->_parent;if (x->_parent == NIL)_root = y;else if (x == x->_parent->_left)x->_parent->_left = y;elsex->_parent->_right = y;y->_left = x;x->_parent = y;}// 右旋修正void RotateR(Node* x) {Node* y = x->_left;x->_left = y->_right;if (y->_right != NIL)y->_right->_parent = x;y->_parent = x->_parent;if (x->_parent == NIL)_root = y;else if (x == x->_parent->_right)x->_parent->_right = y;elsex->_parent->_left = y;y->_right = x;x->_parent = y;}void FixInsert(Node* z) {while (z->_parent->_col == RED) {Node* g = z->_parent->_parent;if (z->_parent == g->_left) {Node* u = g->_right;if (u->_col == RED) { // Case 1z->_parent->_col = BLACK;u->_col = BLACK;g->_col = RED;z = g;} else {if (z == z->_parent->_right) { // Case 2z = z->_parent;RotateL(z);}// Case 3z->_parent->_col = BLACK;g->_col = RED;RotateR(g);}} else { // 对称处理[4,6]Node* u = g->_left;if (u->_col == RED) {z->_parent->_col = BLACK;u->_col = BLACK;g->_col = RED;z = g;} else {if (z == z->_parent->_left) {z = z->_parent;RotateR(z);}z->_parent->_col = BLACK;g->_col = RED;RotateL(g);}}if (z == _root) break;}_root->_col = BLACK; // 强制根节点为黑[4,8]}
};// 测试用例
int main() {RBTree<int, int> tree;// 测试插入序列(触发所有修复情况)int arr[] = {10, 20, 30, 40, 50, 60, 70, 80, 90};for (auto num : arr) {tree.Insert(make_pair(num, num));}return 0;
}

八、应用场景

  1. C++ STLmap/set底层实现
  2. Java集合TreeMap的平衡机制
  3. Linux内核:进程调度CFS算法

相关文章:

  • 公链钱包开发:技术逻辑与产品设计实践
  • Asp.Net Core IIS发布后PUT、DELETE请求错误405
  • 飞云分仓操盘副图指标操作技术图文分解
  • Ceph PG unfound/lost 问题排查与解决
  • 101alpah_第5个alpha学习
  • 电子电气架构 --- 如何有助于提安全性并减少事故
  • Spark缓存--cache方法
  • 力扣:多数元素
  • 【C/C++】RPC与线程间通信:高效设计的关键选择
  • 香港国际交易节奏解析:结构性波动背后的信号逻辑
  • 【软件设计师:数据库】13.数据库控制与安全
  • 关于多版本CUDA共存的研究,是否能一台机子装两个CUDA 版本并正常切换使用
  • Vue2:引入公共JS,通过this调用
  • 前端基础之《Vue(15)—组件通信(2)》
  • 【漫话机器学习系列】247.当 N=整个母体(WHEN N=POPULATION)
  • vue2 两种路由跳转方式
  • 网络化:DevOps 工程的必要基础(Networking: The Essential Foundation for DevOps Engineering)
  • 信息学奥赛一本通 1511:【SCOI2011】糖果 | 洛谷 P3275 [SCOI2011] 糖果
  • 单片机嵌入式滤波算法库
  • 3.2.3 掌握RDD转换算子 - 5. 合并算子 - union()
  • 第一集|《刑警的日子》很生活,《执法者们》有班味
  • 以总理内塔尼亚胡称决心彻底击败哈马斯
  • 九家企业与上海静安集中签约,投资额超10亿元
  • 九部门:对机动车特别是货车排放问题的监管将更加严格
  • 中科院院士魏辅文已卸任江西农业大学校长
  • 吴清:基金业绩差的必须少收管理费,督促基金公司从“重规模”向“重回报”转变