红黑树C/CPP
#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;
else
x->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;
else
x->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;
else
x = x->right;
}
z->parent = y;
// 插入为根节点或子节点
if (y == tree->nil)
tree->root = z;
else if (z->key < y->key)
y->left = z;
else
y->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版本
类设计:
RBTreeNode
表示红黑树的节点。- 使用
shared_ptr
和weak_ptr
管理内存,避免手动释放内存和循环引用问题。RBTree
是红黑树的主体类,包含插入、修复和遍历功能。增强健壮性:
- 使用智能指针避免内存泄漏。
nil
节点用作哨兵节点,减少空指针判断的复杂性。关键功能:
- 左旋转和右旋转操作用于维护红黑树的平衡。
- 插入修复算法确保红黑树性质不被破坏。
内存管理:
- 使用智能指针 (
shared_ptr
和weak_ptr
) 自动管理内存。- 在析构函数中清空树,释放资源。
调试功能:
- 提供
inorderTraversal()
函数,按中序输出节点的键值和颜色,便于验证红黑树结构。