一下是红黑树增删查,包含了一个完整的demo。
1. 由于插入操作比较简单,就不讲了直接上代码:
/**
* @brief Left rotate.
* step:
* 1. right child becomes the parent node, if current node`s parrent is null,
* the right node becomes root node.
* 2. right child`s left child becomes current node`s right node.
* 3. current node becomes right child`s left child.
* current node = previous parent node.
* eg:left node a.
* a c
* / \ left rotate / \
* b c ===============>> a g
* / \ / \ / \
* d e f g b f
* / \
* d e
* @return rd_node_t*
*
* @anchor cj
*/
void left_rotate(rd_node_t **root, rd_node_t *cur_node)
{
rd_node_t *right_node = cur_node->right;
/* step 1 */
right_node->parent = cur_node->parent;
if (!cur_node->parent) {
/* current node is root. */
*root = right_node;
} else if (cur_node == cur_node->parent->left) {
/* if current node is in left tree. */
cur_node->parent->left = right_node;
} else {
/* current node is right tree. */
cur_node->parent->right = right_node;
}
/* step 2 */
cur_node->right = right_node->left;
if (right_node->left) {
right_node->left->parent = cur_node;
}
/* step 3 */
right_node->left = cur_node;
cur_node->parent = right_node;
}
/**
* @brief right rotate.
* step:
* 1. left child becomes the parent node.if current node`s parrent is null,
* the left node becomes root node.
* 2. left child`s right child becomes current node`s right node.
* 3. current node becomes right child`s left child.
* current node = previous parent node.
* eg:right node a.
* a b
* / \ right rotate / \
* b c ===============>> d a
* / \ / \ / \
* d e f g e c
* / \
* f g
* @return rd_node_t*
*
* @anchor cj
*/
void right_rotate(rd_node_t **root, rd_node_t *cur_node)
{
rd_node_t *left_node = cur_node->left;
struct test_info *info = NULL;
/* step 1 */
left_node->parent = cur_node->parent;
if (!cur_node->parent) {
/* root node. */
*root = left_node;
} else if (cur_node == cur_node->parent->left) {
/* current node is left tree. */
cur_node->parent->left = left_node;
} else {
/* current node is right tree. */
cur_node->parent->right = left_node;
}
/* step 2. */
cur_node->left = left_node->right;
if (left_node->right) {
left_node->right->parent = cur_node;
}
/* step 3. */
cur_node->parent = left_node;
left_node->right = cur_node;
}
/**
* @brief 红黑树性质
* 1. 每个节点要么是红色,要么是黑色。
* 2. 根节点是黑色。
* 3. 每个叶子节点(NIL节点)是黑色。----其实就是空指针叶子
* 4. 如果一个节点是红色,那么它的两个子节点都是黑色。 ----- 插入一个节点要默认成红色原因,NIL节点是黑色的。
* 5. 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。
*
*/
/**
* @brief fix red black tree
* step:
* 插入修正:
* 当向红黑树中插入一个节点时,会破坏红黑树的平衡性质。为了修正这种破坏,需要进行以下操作:
*
* a) 如果插入的是根节点,直接将其染成黑色。
* b) 如果插入的节点的父节点是黑色的,不需要做任何修正。
* c) 如果插入的节点的父节点是红色的,需要进行下面的修正操作:
* case 1. 当前节点的父节点是红色,且当前节点的祖父节点的另一个子节点(叔叔节点)也是红色
* (01)将“父节点”设为黑色。(02)将“叔叔节点”设为黑色。(03)将“祖父节点”设为“红色” (04)将“祖节点”设为“当前节点”(红色节点);即,之后继续对“当前节点”进行操作.
* case 2. 父亲节点是左子树,当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的右孩子
* (01)将“父节点”作为“新的当前节点” (02)以“新的当前节点”为支点进行左旋。
* case 3. 父亲节点是左子树,当前节点的父节点是红色,叔叔节点是黑色,且当前节点是其父节点的左孩子
* (01)将“父节点”设为“黑色 (02)将“祖父节点”设为“红色”。(03)以“祖父节点”为支点进行右旋。
* case 4. 父亲节点是右子树,叔叔节点为黑色或者不存在,当前节点是父节点的左子节点,将设置当前节点为父节点,并以更新后的节点为支点进行右旋。
* case 5. 父亲节点是右子树,叔叔节点为黑色或者不存在,当前节点是父节点的右子节点,将当前节点的父节点染黑,祖父节点染红,设置当前节点为祖父节点,并以更新后的当前节点为支点进行左旋。
* @author cj.2023-12-28
*
* @return NULL
*/
void rd_fix_insert(rd_node_t **root, rd_node_t *cur_node)
{
rd_node_t *uncle;
/* 当前是根节点,直接染黑;如果父节点是红色,需要调整;由于根节点始终是黑色的,所以如果父节点是根节点时就不需要遍历调整了 */
while (cur_node && cur_node->parent && cur_node->parent->parent && (cur_node->parent->color == RD_RED)) {
if (cur_node->parent->parent->left == cur_node->parent) { /* 父节点是左子树,叔叔节点是右子树 */
uncle = cur_node->parent->parent->right;
} else { /* 父节点是右子树,叔叔节点是左子树 */
uncle = cur_node->parent->parent->left;
}
/* 如果叔叔节点存在,则查看叔叔节点是否为红色,如果为红色,则叔叔节点和父亲节点染黑,祖父节点染红,并将当前节点置为祖父节点继续判断 */
if (uncle && uncle->color == RD_RED) {
uncle->color = RD_BLACK;
cur_node->parent->color = RD_BLACK;
cur_node->parent->parent->color = RD_RED;
cur_node = cur_node->parent->parent;
continue;
} else {
/* 如果父亲节点是左子树 */
if (cur_node->parent->parent->left == cur_node->parent) {
/* 如果叔叔节点不存在或者是黑色,且插入节点为左子节点,则将父节点染黑,祖父节点染红,并以祖父节点为支点进行右旋 */
if (cur_node->parent->left == cur_node) {
cur_node->parent->color = RD_BLACK;
cur_node->parent->parent->color = RD_RED;
cur_node = cur_node->parent->parent;
right_rotate(root, cur_node);
} else {
/* 如果插入节点是右子树,并以父节作为当前节点,以父节点为支点左旋 */
cur_node = cur_node->parent;
left_rotate(root, cur_node);
}
} else { /* 如果父亲节点是右子树 */
/* 如果叔叔节点不存在或者是黑色,且插入节点为右子节点,则将父节点染黑,祖父节点染红,并以祖父节点为支点进行右旋 */
if (cur_node->parent->right ==