红黑树(Red - Black Tree)
1.定义
红黑树是一种自平衡的二叉查找树,它在每一个节点上增加另一个存储位来表示节点的颜色,可以是红色或者黑色。通过这些颜色的约束,红黑树能够保证从根到叶子节点的最长路径不会超过最短路径的两倍,从而保持大致的平衡。
2.性质
1.节点是红色或者黑色。
2.根节点是黑色。
3.叶子节点(空节点)是黑色。
4.如果一个节点是红色,则它的两个子节点都是黑色。(不能有两个连续的红色节点)
5.从任意节点到其每个叶子的所有路径都包含相同数量的黑色节点。
以下是红黑树的简单实现代码(仅包含插入操作):
#include <iostream>
#include<vector>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
// 定义节点颜色
typedef enum { RED, BLACK } Color;
// 定义红黑树节点
typedef struct RBTreeNode {
int key;
Color color;
struct RBTreeNode* left;
struct RBTreeNode* right;
struct RBTreeNode* parent;
} RBTreeNode;
// 创建新节点
RBTreeNode* createNode(int key) {
RBTreeNode* newNode = (RBTreeNode*)malloc(sizeof(RBTreeNode));
newNode->key = key;
newNode->color = RED; // 新节点默认为红色
newNode->left = NULL;
newNode->right = NULL;
newNode->parent = NULL;
return newNode;
}
// 左旋操作
void leftRotate(RBTreeNode** root, RBTreeNode* x) {
RBTreeNode* y = x->right; // 设置y
x->right = y->left; // 转移y的左子树到x的右子树
if (y->left != NULL) {
y->left->parent = x;
}
y->parent = x->parent; // 链接x的父节点到y
if (x->parent == NULL) {
*root = y;
}
else if (x == x->parent->left) {
x->parent->left = y;
}
else {
x->parent->right = y;
}
y->left = x; // 把x放到y的左子树
x->parent = y;
}
// 右旋操作
void rightRotate(RBTreeNode** root, RBTreeNode* y) {
RBTreeNode* x = y->left; // 设置x
y->left = x->right; // 转移x的右子树到y的左子树
if (x->right != NULL) {
x->right->parent = y;
}
x->parent = y->parent; // 链接y的父节点到x
if (y->parent == NULL) {
*root = x;
}
else if (y == y->parent->right) {
y->parent->right = x;
}
else {
y->parent->left = x;
}
x->right = y; // 把y放到x的右子树
y->parent = x;
}
// 修复插入操作后的红黑树性质
void fixInsert(RBTreeNode** root, RBTreeNode* newNode) {
RBTreeNode* uncle;
while (newNode != *root && newNode->parent->color == RED) {
if (newNode->parent == newNode->parent->parent->left) {
uncle = newNode->parent->parent->right; // 叔叔节点
if (uncle != NULL && uncle->color == RED) {
// 情况1:叔叔是红色
newNode->parent->color = BLACK;
uncle->color = BLACK;
newNode->parent->parent->color = RED;
newNode = newNode->parent->parent;
}
else {
if (newNode == newNode->parent->right) {
// 情况2:叔叔是黑色,且新节点是右孩子
newNode = newNode->parent;
leftRotate(root, newNode);
}
// 情况3:叔叔是黑色,且新节点是左孩子
newNode->parent->color = BLACK;
newNode->parent->parent->color = RED;
rightRotate(root, newNode->parent->parent);
}
}
else {
uncle = newNode->parent->parent->left; // 叔叔节点
if (uncle != NULL && uncle->color == RED) {
// 情况1:叔叔是红色
newNode->parent->color = BLACK;
uncle->color = BLACK;
newNode->parent->parent->color = RED;
newNode = newNode->parent->parent;
}
else {
if (newNode == newNode->parent->left) {
// 情况2:叔叔是黑色,且新节点是左孩子
newNode = newNode->parent;
rightRotate(root, newNode);
}
// 情况3:叔叔是黑色,且新节点是右孩子
newNode->parent->color = BLACK;
newNode->parent->parent->color = RED;
leftRotate(root, newNode->parent->parent);
}
}
}
(*root)->color = BLACK; // 根节点必须是黑色
}
// 插入新节点
void insert(RBTreeNode** root, int key) {
RBTreeNode* newNode = createNode(key);
RBTreeNode* current = *root;
RBTreeNode* parent = NULL;
// 查找插入位置
while (current != NULL) {
parent = current;
if (newNode->key < current->key) {
current = current->left;
}
else {
current = current->right;
}
}
newNode->parent = parent; // 设置父节点
if (parent == NULL) {
*root = newNode; // 如果树为空,新节点成为根节点
}
else if (newNode->key < parent->key) {
parent->left = newNode; // 插入到父节点的左子树
}
else {
parent->right = newNode; // 插入到父节点的右子树
}
fixInsert(root, newNode); // 修复红黑树性质
}
// 打印红黑树(中序遍历)
void inorderTraversal(RBTreeNode* root)
{
if (root != NULL) {
inorderTraversal(root->left);
printf("%d(%s) ", root->key, root->color == RED ? "RED" : "BLACK");
inorderTraversal(root->right);
}
}
int main()
{
RBTreeNode* root = NULL;
insert(&root, 10);
insert(&root, 20);
insert(&root, 30);
insert(&root, 40);
insert(&root, 50);
printf("Inorder traversal of the constructed Red - Black Tree is:\n");
inorderTraversal(root);
printf("\n");
return 0;
}
代码运行结果:
说明:以上代码来自于Kimi AI助手。
好文链接: