红黑树的性质
用来判断红黑树的性质
红黑树的应用
关于Linux服务器的环境配置
1.vm虚拟机安装一个Linux系统
2.在上一步的基础上再在系统安装samba+ssh+gcc编译器
smb用于远程访问共享文件夹;ssh用于xshell远程连接编写代码;
3.代码编辑器 vscode/sourceinsight
红黑树的结构体定义
红黑树子节点定义
//定义一个红黑树的模板文件
#define reboot_entry(name,type) \
struct name{ \
unsigned char color; \
struct type rbtree_node *parent; \
struct type rbtree_node *left; \
struct type rbtree_node *right; \
}
typedef int KEY_TYPE; //用来定义key的任意类型
typedef struct _rbtree_node {
KEY_TYPE key;
void *value;
// value
#if 1 //适合单个红黑树
//rbtree
unsigned char color;
struct rbtree_node *parent;
struct rbtree_node *left;
struct rbtree_node *right;
#else //可重复利用避免多次构建导致代码冗余
reboot_entry( , _rbtree_node) node;
//reboot_entry( , _rbtree_node) a;
//reboot_entry( , _rbtree_node) b;
//reboot_entry( , _rbtree_node) c;
#endif // 0
// end
//
} rbtree_node;
红黑树的根节点定义
typedef struct rbtree {
rbtree_node *root;
rbtree_node *nil; // NULL
} rbtree;
红黑树的旋转
在红黑树的结构遭到破坏的时候我们会将其旋转旋转有俩中形势分为左旋和右旋为了树的平衡 左旋和右旋最多的旋转次数即它的高度
左旋实现
结合上图: x的右指针 指向y的左指针 y的左指针 指向x y的父节点指向 x的父节点 x的叶子节点指向y
void rbtree_left_rotate(rbtree *T, rbtree_node *x) {
// NULL --> T->nil
if (x == T->nil) return ;
// 1
rbtree_node *y = x->right;
x->right = y->left;
//如果y的左指针是叶子节点就不需要更改
if (y->left != T->nil) {
y->left->parent = x;
}
// 2
y->parent = x->parent;
//判断x是否为空
if (x->parent == T->nil) {//如果x的父节点是无 意味着x是根节点
T->root = y;
} else if (x == x->parent->left) {//如果x父节点有那就判断x是左叶子还是右叶子
x->parent->left = y;
} else {
x->parent->right = y;
}
// 3
y->left = x;
x->parent = y;
}
右旋实现
结合上图: y的右指针 指向x的左指针 x的左指针 指向y x的父节点指向 y的父节点 y的叶子节点指向x
// x --> y, y -->x
// left --> right, right --> left
void rbtree_right_rotate(rbtree *T, rbtree_node *y) {
// NULL --> T->nil
if (y == T->nil) return ;
// 1
rbtree_node *x = y->left;
y->left = x->right;
if (y->left != T->nil) {
y->left->parent = x;
}
// 2
y->parent = x->parent;
if (x->parent == T->nil) {
T->root = y;
} else if (x == x->parent->left) {
x->parent->left = y;
} else {
x->parent->right = y;
}
// 3
y->left = x;
x->parent = y;
}
红黑树的节点插入
void rbtree_insert(rbtree *T, rbtree_node *z) {
rbtree_node *y = T->nil;
rbtree_node *x = T->root;
//遍历红黑树
while (x != T->nil) {
//y始终指向x的父节点
y = x;
//插入的值小于叶子的值插左叶子
if (z->key < x->key) {
x = x->left;
} else if (z->key > x->key) {
x = x->right;
} else { //Exist
//当插入的时候遇见节点值和插入值相等的时候 具体操作取决于具体业务
}
}
z->parent = y;
if (y == T->nil) {
T->root = z;
} else if (z->key < y->key) {
y->left = z;
} else {
y->right = z;
}
// z -->
z->color = RED;
z->left = T->nil;
z->right = T->nil;
//
}
当插入的时候遇见节点值和插入值相等的时候 具体操作取决于具体业务
当插入的子节点默认为红色的时候满足了红黑树性质的除4之外的条件这时候就需要去判断
void rbtree_insert_fixup(rbtree *T, rbtree_node *z) {
//
// z->color == RED
// z->parent->color == RED
// z--> RED
while (z->parent->color == RED) { //
//找到插入节点的父节点的父节点
if (z->parent == z->parent->parent->left) {
y = z->parent->parent->right; //
//判断黑红 对应是图一
if (y->color == RED) {
z->parent->color = BLACK;
z->parent->parent->color = RED;
y->color = BLACK;
z = z->parent->parent; //
} else {
//对应图二
if (z = z->parent->right) {
z = z->parent;
rbtree_left_rotate(T, z);
}
//对应图三 根据上一次(图二的转换的迭代导致 父节点和祖父节点颜色冲突 需要旋转解决
z->parent->color = BLACK;
z->parent->parent->color = RED;
rbtree_right_rotate(T, z->parent->parent);
}
}
}
图三因为图二转换之后父,祖父节点颜色冲突且比较重(节点数量比较多)需要进行右旋转操作使得左右平衡 平衡的是黑高
红黑树的删除
对于开发中来说 只需要了解红黑树的时间复杂度 单独实现很少 最好可以自己实现一下红黑树
1.epoll的事件管理