#pragma once #include <iostream> #include <iomanip> using namespace std; enum RBTreeColor { RED, BLACK }; template <typename T> struct RBTreeNode { RBTreeNode(T value, RBTreeColor c) : key(value), color(c), left(nullptr), right(nullptr), parent(nullptr) {} RBTreeNode(T value, RBTreeColor c, RBTreeNode* l, RBTreeNode* r, RBTreeNode* p) : key(value), color(c), left(l), right(r), parent(p) {} T key; RBTreeColor color; RBTreeNode* left; RBTreeNode* right; RBTreeNode* parent; }; template <typename T> class RBTree { public: typedef RBTreeNode<T> Node; public: RBTree() :rootTree(nullptr) {} ~RBTree() { clear(); } //查找 //前序遍历 void preOrder() { preOrder(rootTree); } //中序遍历 void inOrder() { inOrder(rootTree); } //后序遍历 void postOrder() { postOrder(rootTree); } //最大值 T max(); //最小值 T min(); //打印 void print(); //修改 //插入 void insert(T key); //删除 void remove(T key); // (递归实现)查找"二叉树"中键值为key的节点 Node* search(T key); //清除 void clear(); private: //插入 void insert(Node* &root, Node* node); //插入修正 void insertFix(Node* &root, Node* node); //左旋 void leftRotate(Node* &root, Node* x); //右旋 void rightRotate(Node* &root, Node* y); //删除 void remove(Node* &root, Node* node); //删除修正 void removeFix(Node* &root, Node* node, Node* parent); // (递归实现)查找"二叉树"中键值为key的节点 Node* search(Node* tree, T key); void preOrder(Node *tree); void inOrder(Node *tree); void postOrder(Node *tree); Node* max(Node *tree); Node* min(Node *tree); void destroy(Node* &tree); void print(Node* tree, T key, int direction); private: Node* rootTree; }; //插入 template <typename T> void RBTree<T>::insert(T key) { Node* z = nullptr; if ((z = new Node(key, BLACK)) == nullptr) return; insert(rootTree, z); } //插入 template <typename T> void RBTree<T>::insert(Node* &root, Node* node) { Node* y = nullptr; Node* x = root; //1. 当做普通二叉查找树,将节点插入 while (x != nullptr) { y = x; if (node->key < y->key) { x = y->left; } else { x = y->right; } } node->parent = y; if (y != nullptr) { if (node->key < y->key) { y->left = node; } else { y->right = node; } } else { root = node; } //2. 设置节点为红色 node->color = RED; //3. 颜色修正 insertFix(root, node); } //插入修正 template <typename T> void RBTree<T>::insertFix(Node* &root, Node* node) { Node *parent, *gparent; while ((parent = node->parent) && (parent->color == RED)) { gparent = parent->parent; //父节点是祖父节点的左孩子 if (parent == gparent->left) { //case 1: 叔叔节点是红色 { Node* uncle = gparent->right; if (uncle && (uncle->color == RED)) { uncle->color = BLACK; parent->color = BLACK; gparent->color = RED; node = gparent; continue; } } //叔叔节点是黑色,通过旋转case 2可以转为case 3 { //case 2: 叔叔节点是黑色,且当前节点是右孩子 if (parent->right == node) { Node* temp; leftRotate(root, parent); temp = parent; parent = node; node = temp; //到这里情况会转为case 3 } //case 3: 叔叔节点是黑色,且当前节点是左孩子。 parent->color = BLACK; gparent->color = RED; rightRotate(root, gparent); } } else { //case 1: 叔叔节点是红色 { Node* uncle = gparent->left; if (uncle && (uncle->color == RED)) { uncle->color = BLACK; parent->color = BLACK; gparent->color = RED; node = gparent; continue; } } //叔叔节点是黑色,通过旋转case 2可以转为case 3 { //case 2: 叔叔节点是黑色,且当前节点是右孩子 if (parent->left == node) { Node* temp; rightRotate(root, parent); temp = parent; parent = node; node = temp; //到这里情况会转为case 3 } //case 3: 叔叔节点是黑色,且当前节点是左孩子。 parent->color = BLACK; gparent->color = RED; leftRotate(root, gparent); } } } //设置根节点为黑色 root->color = BLACK; } /* * 对红黑树的节点(x)进行左旋转 * * 左旋示意图(对节点x进行左旋): * px px * / / * x y * / --(左旋)--> / # * lx y x ry * / / * ly ry lx ly * * */ //左旋 template <typename T> void RBTree<T>::leftRotate(Node* &root, Node* x) { Node* y = x->right; //将“y的左孩子”设为“x的右孩子” x->right = y->left; if (y->left != nullptr) { y->left->parent = x; } y->parent = x->parent; if (x->parent == nullptr) { root = y; } else { if (x->parent->left == x) { x->parent->left = y; } else { x->parent->right = y; } } y->left = x; x->parent = y; } /* * 对红黑树的节点(y)进行右旋转 * * 右旋示意图(对节点y进行左旋): * py py * / / * y x * / --(右旋)--> / # * x ry lx y * / / # * lx rx rx ry * */ //右旋 template <typename T> void RBTree<T>::rightRotate(Node* &root, Node* y) { Node *x = y->left; //调整y左孩子 y->left = x->right; if (x->right != nullptr) { x->right->parent = nullptr; } //调整x节点 x->parent = y->parent; if (y->parent == nullptr) { root = x; } else { if (y->parent->left == y) { y->parent->left = x; } else { y->parent->right = x; } } x->right = y; //调整y y->parent = x; } //删除 template <typename T> void RBTree<T>::remove(T key) { Node* z; if ((z = search(key)) != nullptr) { remove(rootTree, z); } } //删除 template <typename T> void RBTree<T>::remove(Node* &root, Node* node) { Node *child, *parent; RBTreeColor color; //1.删除节点:当作普通二叉树 //2.删除后,修正颜色 //case 1:节点有两个孩子 if ((node->left != nullptr) && (node->right != nullptr)) { //查找取代节点 Node* replace = node; //获取后继节点 replace = replace->right; while (replace->left != nullptr) { replace = replace->left; } //移动后继节点 if (node->parent) { if (node->parent->left == node) { node->parent->left = replace; } else { node->parent->right = replace; } } else { root = replace; } //后继节点有孩子一定是右孩子 child = replace->right; parent = replace->parent; color = replace->color; //分两种情况,replace是否是node的子孩子 if (parent == node) { //子孩子比较简单,直接删除node,replace替换上 parent = replace; } else { // if (child) { child->parent = parent; } parent->left = child; replace->right = node->right; node->right = replace; } replace->parent = node->parent; replace->color = node->color; replace->left = node->left; node->left->parent = replace; //节点为黑色需要修正 if (color == BLACK) { removeFix(root, child, parent); } delete node; return; } //case 2:含有一个孩子或者无 if (node->left != nullptr) { child = node->left; } else { child = node->right; } parent = node->parent; color = node->color; if (child) { child->parent = parent; } if (parent) { if (parent->left == node) { parent->left = child; } else { parent->right = child; } } else { root = child; } if (color == BLACK) { removeFix(root, child, parent); } delete node; } //删除修正 template <typename T> void RBTree<T>::removeFix(Node* &root, Node* node, Node* parent) { Node* other; while ((!node || node->color == BLACK) && node != root) { if (parent->left == node) { other = parent->right; //case 1:兄弟是红色 ==> 调整为case 2 3 4 //此时parent任然是不平衡的 if (other->color == RED) { other->color = BLACK; parent->color = RED; leftRotate(root, parent); other = parent->right; } //case 2:兄弟w是黑色,且w两个孩子也是黑色 if ((!other->left || other->left->color == BLACK) && (!other->right || other->right->color == BLACK)) { other->color = RED; node = parent; parent = node->parent; } else { //case 3:兄弟w是黑色,且w的左孩子是红色,右孩子是黑色 ==> 调整为case 4 if (!other->right || other->right->color == BLACK) { other->left->color = BLACK; other->color = RED; rightRotate(root, other); other = parent->right; } //case 4:兄弟w是黑色,且w的右孩子为红色 other->color = parent->color; parent->color = BLACK; other->right->color = BLACK; leftRotate(root, parent); node = root; break; } } else { //右节点,情况相反 other = parent->left; //case 1:兄弟是红色 ==> 调整为case 2 3 4 //此时parent任然是不平衡的 if (other->color == RED) { other->color = BLACK; parent->color = RED; leftRotate(root, parent); other = parent->left; } //case 2:兄弟w是黑色,且w两个孩子也是黑色 if ((!other->left || other->left->color == BLACK) && (!other->right || other->right->color == BLACK)) { other->color = RED; node = parent; parent = node->parent; } else { //case 3:兄弟w是黑色,且w的左孩子是红色,右孩子是黑色 ==> 调整为case 4 if (!other->left || other->left->color == BLACK) { other->right->color = BLACK; other->color = RED; rightRotate(root, other); other = parent->left; } //case 4:兄弟w是黑色,且w的右孩子为红色 other->color = parent->color; parent->color = BLACK; other->left->color = BLACK; leftRotate(root, parent); node = root; break; } } } if (node) { node->color = BLACK; } } template <typename T> typename RBTree<T>::Node* RBTree<T>::search(Node* tree, T key) { if (tree == nullptr || tree->key == key) { return tree; } if (key < tree->key) { return search(tree->left, key); } else { return search(tree->right, key); } } template <typename T> typename RBTree<T>::Node* RBTree<T>::search(T key) { return search(rootTree, key); } template <typename T> typename RBTree<T>::Node* RBTree<T>::max(Node *tree) { if (!tree) return nullptr; Node* x = tree; while (x->right) { x = x->right; } return x; } template <typename T> T RBTree<T>::max() { Node* x = max(rootTree); if (x) { return x->key; } else { return (T)nullptr; } } template <typename T> typename RBTree<T>::Node* RBTree<T>::min(Node *tree) { if (!tree) return nullptr; Node* x = tree; while (x->left) { x = x->left; } return x; } template <typename T> T RBTree<T>::min() { Node* x = min(rootTree); if (x) { return x->key; } else { return (T)nullptr; } } template <typename T> void RBTree<T>::preOrder(Node *tree) { if (tree == nullptr) return; std::cout << tree->key << " "; preOrder(tree->left); preOrder(tree->right); } template <typename T> void RBTree<T>::inOrder(Node *tree) { if (!tree) return; inOrder(tree->left); std::cout << tree->key << " "; inOrder(tree->right); } template <typename T> void RBTree<T>::postOrder(Node *tree) { if (!tree) return; postOrder(tree->left); postOrder(tree->right); std::cout << tree->key << " "; } template <typename T> void RBTree<T>::clear() { std::cout << "===destroy: "; destroy(rootTree); std::cout << std::endl; } template <typename T> void RBTree<T>::destroy(Node* &tree) { if (tree == nullptr) return; if (tree->left) { destroy(tree->left); } if (tree->right) { destroy(tree->right); } std::cout << tree->key << " "; delete tree; tree = nullptr; } /* * 打印"二叉查找树" * * key -- 节点的键值 * direction -- 0,表示该节点是根节点; * -1,表示该节点是它的父结点的左孩子; * 1,表示该节点是它的父结点的右孩子。 */ template < typename T> void RBTree<T>::print(Node* tree, T key, int direction) { if (tree != nullptr) { if (direction == 0) // tree是根节点 cout << setw(2) << tree->key << "(B) is root" << endl; else // tree是分支节点 cout << setw(2) << tree->key << ( (tree->color == RED) ? "(R)" : "(B)" )<< " is " << setw(2) << key << "'s " << setw(12) << (direction == 1 ? "right child" : "left child") << endl; print(tree->left, tree->key, -1); print(tree->right, tree->key, 1); } } template < typename T> void RBTree<T>::print() { if (rootTree != NULL) print(rootTree, rootTree->key, 0); }