红黑树C实现
1.红黑树演示动画 Red/Black Tree Visualization (usfca.edu)
2.红黑树插入节点后的四种旋转状态:以下均以插入节点位置作为参考目标
L(父节点红色)L(插入节点是左子节点红色)-> 以祖父节点为支点右旋
L(父节点红色)R(插入节点是右子节点红色)-> 先以父节点为支点左旋,再以祖父节点为支点右旋
R(父节点红色)R(插入节点是右子节点红色)-> 以祖父节点为支点左旋
R(父节点红色)L(插入节点是左子节点红色)-> 先以父节点为支点右旋,再以祖父节点为支点左旋
3.插入难点:
当祖父节点黑色、父节点 和 叔父节点(即为父节点的兄弟节点)都为红色时,将父节点和叔父节点变为黑色,祖父节点变为红色,然后再以祖父节点为参数传入平衡递归。
4.删除难点
当删除节点(叶子节点) 父节点、兄弟节点(叶子节点)都是黑色, 将兄弟节点变为红色,然后将父节点为参数带入平衡递归。
// rbtree.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 #include <iostream> typedef int RBTYPE; #define RED 0 #define BLACK 1 // 红黑树节点 typedef struct RBNode { struct RBNode* left; struct RBNode* right; struct RBNode* parent; unsigned char color; RBTYPE value; }RBNODE, *PRBNODE; typedef struct RBTree { PRBNODE root; PRBNODE nil; }RBTREE, *PRBTREE; PRBTREE create_tree() { PRBTREE rbtree = new RBTREE; rbtree->nil = new RBNODE; rbtree->nil->color = BLACK; rbtree->nil->left = rbtree->nil->right = NULL; rbtree->root = rbtree->nil; return rbtree; } PRBNODE create_rbnode(RBTYPE value, PRBNODE nil) { PRBNODE pnode = new RBNODE; pnode->color = RED; pnode->left = pnode->right = pnode->parent = nil; pnode->value = value; return pnode; } //1.插入节点到叶子节点 success 1 failed 0 PRBNODE insert_leaf_node(PRBTREE rbtree, RBTYPE value) { PRBNODE node = rbtree->root, node_parent = rbtree->nil; while (node != rbtree->nil) { node_parent = node; if (value < node->value) { node = node->left; } else if (value > node->value) { node = node->right; } else { return rbtree->nil; } } // 找到节点插入位置 PRBNODE leaf_node = create_rbnode(value, rbtree->nil); if (node_parent != rbtree->nil) { leaf_node->parent = node_parent; if (value < node_parent->value) { node_parent->left = leaf_node; } else { node_parent->right = leaf_node; } } else { // 插入节点为根节点 leaf_node->color = BLACK; rbtree->root = leaf_node; } return leaf_node; } void left_rotate(PRBTREE rbtree, PRBNODE node) { PRBNODE node_right = node->right; node->right = node_right->left; if (node_right->left != rbtree->nil) { node_right->left->parent = node; } if (node->parent == rbtree->nil) { rbtree->root = node_right; } else if (node == node->parent->left) { node->parent->left = node_right; } else if (node == node->parent->right) { node->parent->right = node_right; } node_right->parent = node->parent; node_right->left = node; node->parent = node_right; } //LL void left_left_rotate(PRBTREE rbtree, PRBNODE node) { node->color = RED; node->right->color = BLACK; left_rotate(rbtree, node); } // 右旋 void right_rotate(PRBTREE rbtree, PRBNODE node) { PRBNODE node_left = node->left; node->left = node_left->right; if (node_left->right != rbtree->nil) { node_left->right->parent = node; } if (node->parent == rbtree->nil) { rbtree->root = node_left; } else if (node == node->parent->left) { node->parent->left = node_left; } else { node->parent->right = node_left; } node_left->parent = node->parent; node_left->right = node; node->parent = node_left; } // RR void right_right_rotate(PRBTREE rbtree, PRBNODE node) { node->color = RED; node->left->color = BLACK; right_rotate(rbtree, node); } void color_position_adjustment(PRBTREE rbtree, PRBNODE node); // 将叔父和父节点由红色都变成黑色,若祖父节点不是根节点,则变为红色 void node_uncle_parent_red(PRBTREE rbtree, PRBNODE node_parent, PRBNODE node_uncle) { PRBNODE node_grandparent = node_parent->parent; node_parent->color = BLACK; node_uncle->color = BLACK; if (node_grandparent == rbtree->root) { return; } node_grandparent->color = RED; color_position_adjustment(rbtree, node_grandparent); } void color_position_adjustment(PRBTREE rbtree, PRBNODE node) { PRBNODE node_parent = node->parent; if (node_parent == rbtree->nil) return; PRBNODE node_grandparent = node->parent->parent; if (node_grandparent == rbtree->nil) return; PRBNODE node_uncle = rbtree->nil; //1.判断父节点是否为黑色 if (node_parent->color == BLACK) return; //2.父节点为红色 //2.1 若父节点为祖父节点左子节点 if (node_parent == node_grandparent->left) { node_uncle = node_grandparent->right; // 叔父节点是右子节点 // 叔父节点为黑色 nil也是黑色 if (node_uncle == rbtree->nil || node_uncle->color == BLACK) { // LR 先左旋转为LL if (node == node_parent->right) { left_rotate(rbtree, node_parent); } // LL -> 右旋 right_right_rotate(rbtree, node_grandparent); } // 叔父节点红色 else { // 将叔父和父节点都变成黑色,若祖父节点不是根节点,则变为红色 node_uncle_parent_red(rbtree, node_parent, node_uncle); } } // 2.2若父节点为祖父节点右子节点 else { node_uncle = node_grandparent->left; // 叔父节点为左子节点 且为黑色 if (node_uncle == rbtree->nil || node_uncle->color == BLACK) { // RL -> 先右旋为RR if (node == node_parent->left) { right_rotate(rbtree, node_parent); } // RR -> 左旋 left_left_rotate(rbtree, node_grandparent); } // 叔父节点为红色 else { node_uncle_parent_red(rbtree, node_parent, node_uncle); } } } // 插入节点 bool insert_rbnode(PRBTREE rbtree, RBTYPE value) { PRBNODE node = insert_leaf_node(rbtree, value); if (node == rbtree->nil) return false; // 颜色位置调整 color_position_adjustment(rbtree, node); return true; } void free_node(PRBNODE nil, PRBNODE node) { if (node == nil) { return; } free_node(nil, node->left); free_node(nil, node->right); delete node; } void clear_rbtree(PRBTREE rbtree) { if (rbtree == nullptr) return; free_node(rbtree->nil, rbtree->root); rbtree->root = rbtree->nil; } void free_rbtree(PRBTREE* rbtree) { if (*rbtree == nullptr) return; clear_rbtree(*rbtree); delete (*rbtree)->nil; delete *rbtree; *rbtree = nullptr; } bool isempty_rbtree(PRBTREE rbtree) { if (rbtree == nullptr || rbtree->root == rbtree->nil) return true; return false; } // 查找节点 PRBNODE search_rbnode(RBTYPE value, PRBNODE node, PRBNODE nil) { if (node == nil || node->value == value) return node; PRBNODE result = search_rbnode(value, node->left, nil); if (nil == result) { result = search_rbnode(value, node->right, nil); } return result; } // 查找红黑树键所在位置 PRBNODE search_rbtree(PRBTREE rbtree, RBTYPE value) { if (isempty_rbtree(rbtree)) return rbtree->nil; return search_rbnode(value, rbtree->root, rbtree->nil); } // 中序前驱 PRBNODE mid_order_pre(PRBNODE node, PRBNODE nil) { PRBNODE node_pre = nil; node = node->left; while (node != nil) { node_pre = node; node = node->right; } return node_pre; } // 中序后继 PRBNODE mid_order_next(PRBNODE node, PRBNODE nil) { PRBNODE node_next = nil; node = node->right; while (node != nil) { node_next = node; node = node->left; } return node_next; } // 查找最接近node 键的节点 PRBNODE search_closest_rbnode(PRBNODE node, PRBNODE nil) { PRBNODE closest_node = mid_order_pre(node, nil); if (closest_node == nil) { closest_node = mid_order_next(node, nil); } return closest_node; } // 交换两个节点位置以及颜色 void swap_rbnode_positioin(PRBNODE oldnode, PRBNODE newnode, PRBNODE nil) { PRBNODE tmpleftnode = oldnode->left, tmprightnode = oldnode->right, tmpparentnode = oldnode->parent; int color = oldnode->color; oldnode->left = newnode->left; oldnode->right = newnode->right; oldnode->color = newnode->color; if (oldnode == newnode->parent) { oldnode->parent = newnode; if (tmpleftnode == newnode) { newnode->left = oldnode; newnode->right = tmprightnode; } else if (tmprightnode == newnode) { newnode->left = tmpleftnode; newnode->right = oldnode; } } else { oldnode->parent = newnode->parent; if (newnode->parent->left = newnode) { newnode->parent->left = oldnode; } else { newnode->parent->right = oldnode; } newnode->left = tmpleftnode; newnode->right = tmprightnode; } newnode->parent = tmpparentnode; if (tmpparentnode != nil) { if (oldnode == tmpparentnode->left) { tmpparentnode->left = newnode; } else { tmpparentnode->right = newnode; } } newnode->color = color; if (tmpleftnode == newnode) { newnode->left = oldnode; newnode->right = tmprightnode; } else if(tmprightnode == newnode) { newnode->left = tmpleftnode; newnode->right = oldnode; } else { newnode->left = tmpleftnode; newnode->right = tmprightnode; } } // 找出红色节点 PRBNODE search_red_node(PRBTREE rbtree, PRBNODE node) { if (node == rbtree->nil ||node->color == RED) return rbtree->nil; PRBNODE result = search_red_node(rbtree, node->left); if (result == rbtree->nil) { result = search_red_node(rbtree, node->right); } return result; } // 处理情况:被删节点和父节点以及兄弟节点(兄弟节点两个子节点都是nil)需要平衡 void balance_rbtree(PRBTREE rbtree, PRBNODE node) { if (node == rbtree->nil || node->parent == rbtree->nil) return; PRBNODE node_parent = node->parent; // 父节点为红色 if (node_parent->color == RED) { // node节点是左子节点 if (node == node_parent->left) { left_rotate(rbtree, node_parent); } // node节点是右子节点 else { right_rotate(rbtree, node_parent); } } // 父节点为黑色 else { // node节点是左子节点 if (node == node_parent->left) { // node兄弟节点为红色 PRBNODE node_sibling = node_parent->right; if (node_sibling->color == RED) { node_sibling->color = BLACK; right_rotate(rbtree, node_parent); } // 兄弟节点为黑色 else { // 若兄弟节子节点都存在 if (node_sibling->right->color == RED) { // SR 均为红色 SL 是黑色或红色 node_sibling->right->color = BLACK; left_rotate(rbtree, node_parent); } else if (node_sibling->left->color == RED) { // SL 红色 SR 黑色 node_sibling->left->color = BLACK; right_rotate(rbtree, node_sibling); left_rotate(rbtree, node_parent); } else { // P S SL SR 黑色 // 当走到这一步 说明兄弟节点、兄弟节点的儿子节点 都是黑色, // 没必要再往下了追溯了,继续往上寻找红色节点 node_sibling->color = RED; balance_rbtree(rbtree, node_parent); } } } // node节点是右子节点 else { // node兄弟节点为红色 PRBNODE node_sibling = node_parent->left; if (node_sibling->color == RED) { right_rotate(rbtree, node_parent); node_sibling->color = BLACK; } // 兄弟节点为黑色 else { // 若兄弟节子节点都存在 if (node_sibling->left->color == RED) { // SR 均为红色 SL 是黑色或红色 node_sibling->left->color = BLACK; right_rotate(rbtree, node_parent); } else if (node_sibling->right->color == RED) { // SL 红色 SR 黑色 node_sibling->right->color = BLACK; left_rotate(rbtree, node_sibling); right_rotate(rbtree, node_parent); }else { // P S SL SR 黑色 // 当走到这一步 说明兄弟节点、兄弟节点的儿子节点 都是黑色, // 没必要再往下了追溯了,继续往上寻找红色节点 node_sibling->color = RED; balance_rbtree(rbtree, node_parent); } } } } } void reset_parent_node(PRBNODE node, PRBNODE nil) { if (node == node->parent->left) { node->parent->left = nil; } else { node->parent->right = nil; } } // 删除节点 void delete_rbnode(PRBTREE rbtree, RBTYPE value) { PRBNODE node = search_rbtree(rbtree, value); if (node == rbtree->nil) return; PRBNODE closest_node = search_closest_rbnode(node, rbtree->nil); // 若没有最接近的节点,则删除根节点 if (closest_node == rbtree->nil) { // 是根节点 且就一个节点 if (closest_node == rbtree->root) { rbtree->root = rbtree->nil; delete closest_node; return; } } // 被删节点非叶子节点,且不是一个根节点 else { // 替换两个键 指向 和颜色 swap_rbnode_positioin(node, closest_node, rbtree->nil); } // 若最终被删除节点为红色 if (node->color == RED) { reset_parent_node(node, rbtree->nil); delete node; return; } // 被删节点为黑色 // 若左子节不是nil 则点必定是红色 if (node->left != rbtree->nil) { PRBNODE node_left = node->left; node_left->parent = node->parent; if (node = node->parent->left) { node->parent->left = node_left; } else { node->parent->right = node_left; } } // 若右子节不是nil 则点必定是红色 else if (node->right != rbtree->nil) { PRBNODE node_right = node->right; node_right->parent = node->parent; if (node = node->parent->left) { node->parent->left = node_right; } else { node->parent->right = node_right; } } // 被删节点为叶子节点 黑色 else { // 若最终被删除节点为黑色 PRBNODE node_parent = node->parent; PRBNODE node_brother = rbtree->nil; PRBNODE node_brother_left = rbtree->nil; PRBNODE node_brother_right = rbtree->nil; if (node_parent->left == node) { node_brother = node_parent->right; } else { node_brother = node_parent->left; } if (node_brother != rbtree->nil) { node_brother_left = node_brother->left; node_brother_right = node_brother->right; } // 若父节点为红色,则兄弟节点必为黑色 if (node_parent->color == RED) { // 被删node为左子节点 if (node == node_parent->left) { node_parent->left = rbtree->nil; // 若兄弟节点存在子节点 必是红色 if (node_brother_right != rbtree->nil) { node_parent->color = BLACK; node_brother_right->color = BLACK; node_brother->color = RED; left_rotate(rbtree, node_parent); } else if (node_brother_left != rbtree->nil) { node_parent->color = BLACK; right_rotate(rbtree, node_brother); left_rotate(rbtree, node_parent); } else { node_parent->color = BLACK; node_brother->color = RED; } }// 被删节点为右子节点 else { node_parent->right = rbtree->nil; // 若兄弟节点存在子节点 必是红色 if (node_brother_left != rbtree->nil) { right_rotate(rbtree, node_parent); } else if (node_brother_right != rbtree->nil) { left_rotate(rbtree, node_brother); right_rotate(rbtree, node_parent); } else { node_parent->color = BLACK; node_brother->color = RED; } } } // 父节点为黑色 else { // 被删节点为左子节点 if (node == node_parent->left) { node_parent->left = rbtree->nil; if (node_brother->color == RED) { node_brother->color = BLACK; left_rotate(rbtree, node_parent); }else{ // 兄弟节点为黑色 if (node_brother_right != rbtree->nil) { node_brother_right->color = BLACK; left_rotate(rbtree, node_parent); } else if (node_brother_left != rbtree->nil) { node_brother_left->color = BLACK; right_rotate(rbtree, node_brother); left_rotate(rbtree, node_parent); } else { // 兄弟节点没有叶子节点时 node_brother->color = RED; balance_rbtree(rbtree, node_parent); } } } // 被删节点为右边 else { node_parent->right = rbtree->nil; if (node_brother->color == RED) { node_brother->color = BLACK; right_rotate(rbtree, node_parent); } else { // 兄弟节点为黑色 if (node_brother_left != rbtree->nil) { node_brother_left->color = BLACK; right_rotate(rbtree, node_parent); } else if (node_brother_right != rbtree->nil) { node_brother_right->color = BLACK; left_rotate(rbtree, node_brother); right_rotate(rbtree, node_parent); } else { // 兄弟节点没有叶子节点时 node_brother->color = RED; balance_rbtree(rbtree, node_parent); } } } } } delete node; } // 遍历显示节点 void print_node(PRBNODE nil, PRBNODE node) { if (nil == node) return; print_node(nil, node->left); std::cout << "[" << node->value << ", " << (node->color == RED ? "RED" : "BALCK") << "] "; print_node(nil, node->right); } void print_rbtree(PRBTREE rbtree) { if (rbtree == nullptr) return; print_node(rbtree->nil, rbtree->root); std::cout << std::endl; } #define SIZE 8 int main() { PRBTREE rbtree = create_tree(); for (size_t i = 0; i < SIZE; i++) { if (!insert_rbnode(rbtree, i)) { std::cout << "插入失败: " << i << std::endl; } } print_rbtree(rbtree); RBTYPE value = 5; std::cout << "查找:" << value << std::endl; PRBNODE node = search_rbtree(rbtree, value); if (node != rbtree->nil) { std::cout << "[" << node->value << ", " << (node->color == RED ? "RED" : "BALCK") << "] " << std::endl; } else { std::cout << "未找到" << std::endl; } std::cout << value << " 父节点:" << node->parent->value << std::endl; RBTYPE dvalue = 5; std::cout << "删除点:" << dvalue << std::endl; delete_rbnode(rbtree, dvalue); print_rbtree(rbtree); free_rbtree(&rbtree); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律