• 红黑树--C++实现


    #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);
    }
  • 相关阅读:
    js笔记一:在HTML中使用javascript
    opencv排错总结
    《学习openCV》例程解析 ex_8_2 (轮廓)
    《学习openCV》例程解析 ex_9_3(codeBook模型实现背景减除)
    《学习openCV》例程解析 ex_9_1 (像素片段)
    《学习openCV》例程解析 ex_9_2(背景减除)
    《学习openCV》例程解析 ex_8_3 (轮廓)
    JavaScript鼠标事件
    sumlime text2 快捷键
    HTML字符实体(转)
  • 原文地址:https://www.cnblogs.com/vczf/p/12145462.html
Copyright © 2020-2023  润新知