红黑树C/CPP

server/2024/12/27 7:57:12/
#include <stdio.h>
#include <stdlib.h>// 红黑树节点颜色定义
typedef enum { RED, BLACK } NodeColor;// 红黑树节点结构
typedef struct RBTreeNode {int key;                        // 节点的键值NodeColor color;                // 节点的颜色(红或黑)struct RBTreeNode *left;        // 左子节点struct RBTreeNode *right;       // 右子节点struct RBTreeNode *parent;      // 父节点
} RBTreeNode;// 红黑树结构
typedef struct RBTree {RBTreeNode *root;               // 根节点RBTreeNode *nil;                // 哨兵节点(所有空节点指向这个)
} RBTree;// 创建一个新节点
RBTreeNode *createNode(RBTree *tree, int key) {RBTreeNode *node = (RBTreeNode *)malloc(sizeof(RBTreeNode));if (node == NULL) {fprintf(stderr, "Memory allocation failed for new node.\n");exit(EXIT_FAILURE);}node->key = key;node->color = RED;              // 新插入节点默认为红色node->left = tree->nil;node->right = tree->nil;node->parent = tree->nil;return node;
}// 初始化红黑树
RBTree *createTree() {RBTree *tree = (RBTree *)malloc(sizeof(RBTree));if (tree == NULL) {fprintf(stderr, "Memory allocation failed for tree.\n");exit(EXIT_FAILURE);}// 初始化哨兵节点tree->nil = (RBTreeNode *)malloc(sizeof(RBTreeNode));if (tree->nil == NULL) {fprintf(stderr, "Memory allocation failed for sentinel node.\n");exit(EXIT_FAILURE);}tree->nil->color = BLACK;tree->root = tree->nil;return tree;
}// 左旋转
void leftRotate(RBTree *tree, RBTreeNode *x) {RBTreeNode *y = x->right;x->right = y->left;if (y->left != tree->nil)y->left->parent = x;y->parent = x->parent;if (x->parent == tree->nil)tree->root = y;else if (x == x->parent->left)x->parent->left = y;elsex->parent->right = y;y->left = x;x->parent = y;
}// 右旋转
void rightRotate(RBTree *tree, RBTreeNode *x) {RBTreeNode *y = x->left;x->left = y->right;if (y->right != tree->nil)y->right->parent = x;y->parent = x->parent;if (x->parent == tree->nil)tree->root = y;else if (x == x->parent->right)x->parent->right = y;elsex->parent->left = y;y->right = x;x->parent = y;
}// 插入修复(保持红黑树性质)
void insertFixup(RBTree *tree, RBTreeNode *z) {while (z->parent->color == RED) {if (z->parent == z->parent->parent->left) {RBTreeNode *y = z->parent->parent->right; // 叔叔节点if (y->color == RED) {                  // Case 1: 叔叔是红色z->parent->color = BLACK;y->color = BLACK;z->parent->parent->color = RED;z = z->parent->parent;} else {if (z == z->parent->right) {       // Case 2: 叔叔是黑色,当前节点是右子节点z = z->parent;leftRotate(tree, z);}z->parent->color = BLACK;         // Case 3: 叔叔是黑色,当前节点是左子节点z->parent->parent->color = RED;rightRotate(tree, z->parent->parent);}} else {RBTreeNode *y = z->parent->parent->left; // 叔叔节点if (y->color == RED) {                  // Case 1: 叔叔是红色z->parent->color = BLACK;y->color = BLACK;z->parent->parent->color = RED;z = z->parent->parent;} else {if (z == z->parent->left) {        // Case 2: 叔叔是黑色,当前节点是左子节点z = z->parent;rightRotate(tree, z);}z->parent->color = BLACK;         // Case 3: 叔叔是黑色,当前节点是右子节点z->parent->parent->color = RED;leftRotate(tree, z->parent->parent);}}}tree->root->color = BLACK; // 根节点必须为黑色
}// 插入节点
void rbInsert(RBTree *tree, int key) {RBTreeNode *z = createNode(tree, key);RBTreeNode *y = tree->nil;RBTreeNode *x = tree->root;// 查找插入位置while (x != tree->nil) {y = x;if (z->key < x->key)x = x->left;elsex = x->right;}z->parent = y;// 插入为根节点或子节点if (y == tree->nil)tree->root = z;else if (z->key < y->key)y->left = z;elsey->right = z;z->left = tree->nil;z->right = tree->nil;z->color = RED;// 修复红黑树性质insertFixup(tree, z);
}// 中序遍历(调试用)
void inorderTraversal(RBTree *tree, RBTreeNode *node) {if (node != tree->nil) {inorderTraversal(tree, node->left);printf("%d(%s) ", node->key, node->color == RED ? "R" : "B");inorderTraversal(tree, node->right);}
}// 释放节点
void freeNode(RBTree *tree, RBTreeNode *node) {if (node != tree->nil) {freeNode(tree, node->left);freeNode(tree, node->right);free(node);}
}// 释放红黑树
void freeTree(RBTree *tree) {freeNode(tree, tree->root);free(tree->nil);free(tree);
}// 主函数
int main() {RBTree *tree = createTree();// 插入数据rbInsert(tree, 10);rbInsert(tree, 20);rbInsert(tree, 30);rbInsert(tree, 15);rbInsert(tree, 25);// 中序遍历printf("Inorder Traversal of Red-Black Tree:\n");inorderTraversal(tree, tree->root);printf("\n");// 释放红黑树freeTree(tree);return 0;
}

 C语言版本

  • 结构设计:

    • RBTree 包含根节点和哨兵节点。
    • 哨兵节点用于表示空节点,避免频繁的空指针检查。
  • 关键功能:

    • createNode() 创建一个红色的新节点。
    • leftRotate()rightRotate() 实现红黑树的旋转操作。
    • insertFixup() 修复红黑树插入后的平衡性。
  • 增强健壮性:

    • 内存分配失败时打印错误并终止程序。
    • 所有空节点使用哨兵节点,避免空指针操作。
  • 调试功能:

    • 中序遍历函数 inorderTraversal() 输出红黑树的节点及其颜色,便于调试。
  • 内存管理:

    • 在程序结束时释放分配的内存,避免内存泄漏。
#include <iostream>
#include <memory> // 用于智能指针
using namespace std;// 红黑树节点颜色定义
enum NodeColor { RED, BLACK };// 红黑树节点类
struct RBTreeNode {int key;                         // 节点的键值NodeColor color;                 // 节点的颜色shared_ptr<RBTreeNode> left;     // 左子节点shared_ptr<RBTreeNode> right;    // 右子节点weak_ptr<RBTreeNode> parent;     // 父节点(使用 weak_ptr 避免循环引用)// 构造函数RBTreeNode(int k, NodeColor c): key(k), color(c), left(nullptr), right(nullptr), parent() {}
};// 红黑树类
class RBTree {
private:shared_ptr<RBTreeNode> root;     // 根节点shared_ptr<RBTreeNode> nil;      // 哨兵节点// 左旋转void leftRotate(shared_ptr<RBTreeNode> x) {auto y = x->right;           // y 是 x 的右子节点x->right = y->left;          // 将 y 的左子树移动为 x 的右子树if (y->left != nil) {y->left->parent = x;}y->parent = x->parent;       // 更新 y 的父节点if (x->parent.lock() == nil) {root = y;} else if (x == x->parent.lock()->left) {x->parent.lock()->left = y;} else {x->parent.lock()->right = y;}y->left = x;x->parent = y;}// 右旋转void rightRotate(shared_ptr<RBTreeNode> x) {auto y = x->left;            // y 是 x 的左子节点x->left = y->right;          // 将 y 的右子树移动为 x 的左子树if (y->right != nil) {y->right->parent = x;}y->parent = x->parent;       // 更新 y 的父节点if (x->parent.lock() == nil) {root = y;} else if (x == x->parent.lock()->right) {x->parent.lock()->right = y;} else {x->parent.lock()->left = y;}y->right = x;x->parent = y;}// 插入修复void insertFixup(shared_ptr<RBTreeNode> z) {while (z->parent.lock()->color == RED) {if (z->parent.lock() == z->parent.lock()->parent.lock()->left) {auto y = z->parent.lock()->parent.lock()->right; // 叔叔节点if (y->color == RED) {                          // Case 1: 叔叔是红色z->parent.lock()->color = BLACK;y->color = BLACK;z->parent.lock()->parent.lock()->color = RED;z = z->parent.lock()->parent.lock();} else {if (z == z->parent.lock()->right) {         // Case 2: 当前节点是右子节点z = z->parent.lock();leftRotate(z);}z->parent.lock()->color = BLACK;           // Case 3: 当前节点是左子节点z->parent.lock()->parent.lock()->color = RED;rightRotate(z->parent.lock()->parent.lock());}} else {auto y = z->parent.lock()->parent.lock()->left; // 叔叔节点if (y->color == RED) {                          // Case 1: 叔叔是红色z->parent.lock()->color = BLACK;y->color = BLACK;z->parent.lock()->parent.lock()->color = RED;z = z->parent.lock()->parent.lock();} else {if (z == z->parent.lock()->left) {          // Case 2: 当前节点是左子节点z = z->parent.lock();rightRotate(z);}z->parent.lock()->color = BLACK;           // Case 3: 当前节点是右子节点z->parent.lock()->parent.lock()->color = RED;leftRotate(z->parent.lock()->parent.lock());}}}root->color = BLACK; // 根节点必须为黑色}public:// 构造函数RBTree() {nil = make_shared<RBTreeNode>(0, BLACK); // 初始化哨兵节点root = nil;}// 插入节点void rbInsert(int key) {auto z = make_shared<RBTreeNode>(key, RED); // 创建新节点z->left = nil;z->right = nil;auto y = nil;auto x = root;// 查找插入位置while (x != nil) {y = x;if (z->key < x->key) {x = x->left;} else {x = x->right;}}z->parent = y;// 插入为根节点或子节点if (y == nil) {root = z;} else if (z->key < y->key) {y->left = z;} else {y->right = z;}// 修复红黑树性质insertFixup(z);}// 中序遍历(调试用)void inorderTraversal(shared_ptr<RBTreeNode> node) const {if (node != nil) {inorderTraversal(node->left);cout << node->key << "(" << (node->color == RED ? "R" : "B") << ") ";inorderTraversal(node->right);}}// 中序遍历接口void inorderTraversal() const {inorderTraversal(root);cout << endl;}// 释放节点void freeTree() {root = nil; // 自动释放内存}// 析构函数~RBTree() {freeTree();}
};// 主函数
int main() {RBTree tree;// 插入数据tree.rbInsert(10);tree.rbInsert(20);tree.rbInsert(30);tree.rbInsert(15);tree.rbInsert(25);// 中序遍历cout << "Inorder Traversal of Red-Black Tree:" << endl;tree.inorderTraversal();return 0;
}

CPP版本

  1. 类设计:

    • RBTreeNode 表示红黑树的节点。
    • 使用 shared_ptrweak_ptr 管理内存,避免手动释放内存和循环引用问题。
    • RBTree 是红黑树的主体类,包含插入、修复和遍历功能。
  2. 增强健壮性:

    • 使用智能指针避免内存泄漏。
    • nil 节点用作哨兵节点,减少空指针判断的复杂性。
  3. 关键功能:

    • 左旋转和右旋转操作用于维护红黑树的平衡。
    • 插入修复算法确保红黑树性质不被破坏。
  4. 内存管理:

    • 使用智能指针 (shared_ptrweak_ptr) 自动管理内存。
    • 在析构函数中清空树,释放资源。
  5. 调试功能:

    • 提供 inorderTraversal() 函数,按中序输出节点的键值和颜色,便于验证红黑树结构。

http://www.ppmy.cn/server/153561.html

相关文章

OpenCV相机标定与3D重建(35)计算两幅图像之间本质矩阵(Essential Matrix)的函数findEssentialMat()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 从两幅图像中的对应点计算本质矩阵。 cv::findEssentialMat 是 OpenCV 库中用于计算两幅图像之间本质矩阵&#xff08;Essential Matrix&#xf…

基于 Paimon x Spark 采集分析半结构化 JSON 的优化实践

摘要&#xff1a;本文整理自 阿里巴巴 A 数据湖架构师康凯老师和 Paimon PMC Member 毕岩老师在11月15日 Apache Spark & Paimon Meetup&#xff0c;助力 Lakehouse 架构生产落地上的分享。 文章介绍了阿里巴巴 A 业务基于 Variant 类型的 JSON 链路优化&#xff0c;并从技…

质数分解,用sqrt缩小范围

题目&#xff1a;scanf一个整数&#xff0c;int32范围内&#xff0c;分解为质数序列输出 例如&#xff1a; 12分解为2 2 3 技巧就一个&#xff1a;用sqrt缩小范围 因为uint32(4,294,967,295)(接近43亿个数)范围内有2亿个左右质数&#xff0c;所以&#xff0c;一般不会用缓存去…

DevExpress WPF中文教程:Grid - 如何移动和调整列大小?(二)

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

DP动态规划+贪心题目汇总

文章目录 背包01背包416. 分割等和子集 完全背包279. 完全平方数322. 零钱兑换 两个字符串DPLCR 095. 最长公共子序列139. 单词拆分 单个数组字符串DP5. 最长回文子串300. 最长递增子序列53.最大子数组和152. 乘积最大子数组198. 打家劫舍 三角形120. 三角形最小路径和 贪心121…

【EtherCATBasics】- KRTS C++示例精讲(2)

EtherCATBasics示例讲解 目录 EtherCATBasics示例讲解结构说明代码讲解 项目打开请查看【BaseFunction精讲】。 结构说明 EtherCATBasics&#xff1a;应用层程序&#xff0c;主要用于人机交互、数据显示、内核层数据交互等&#xff1b; EtherCATBasics.h &#xff1a; 数据定义…

Linux系统升级OpenSSH 9.8流程

参考链接&#xff1a; openssh最新版本下载地址&#xff1a;Index of /pub/OpenBSD/OpenSSH/portable/ 注意&#xff1a;openssh9.8需要依赖openssl&#xff0c;版本至少为1.1.1。 一、简介 Openssh存在远程代码执行漏洞(CVE-2024-6387)&#xff0c;攻击者可以成功利用该漏…

深入理解Nginx工作原理及优化技巧

NGINX以高性能的负载均衡器&#xff0c;缓存&#xff0c;和web服务器闻名&#xff0c;驱动了全球超过 40% 最繁忙的网站。在大多数场景下&#xff0c;默认的 NGINX 和 Linux 设置可以很好的工作&#xff0c;但要达到最佳性能&#xff0c;有些时候必须做些调整。 NGINX被广泛应…