268-C++ 红黑树RBTree

36 篇文章 0 订阅
11 篇文章 0 订阅

在这里插入图片描述
最下面的黑色节点是哨兵节点
通常面试的时候都不给出头节点,有头节点会使红黑树变的更加容易
在这里插入图片描述
在这里插入图片描述
红黑树能不能给出三种颜色?就相当于是AVL树,AVL树是三种状态

RB树只要求是大致平衡的,不想AVL树是完全平衡的

下面两个图是等价的,所有路径都包含相同数目的黑色节点
在这里插入图片描述
每次新建节点的默认颜色都是红色

typedef enum {RED = 0,BLACK = 1}ColorType;
typedef int KeyType;
typedef struct rb_node
{
    rb_node* leftchild;
    rb_node* parent;
    rb_node* rightchild;
    ColorType color;
    KeyType key;
}rb_node,*RBTree;
rb_node* BuyNode();
static rb_node* Nil = BuyNode();//哨兵节点
rb_node* BuyNode()
{
    rb_node* s = (rb_node*)malloc(sizeof(rb_node));
    if (nullptr == s) exit(1);
    memset(s, 0, sizeof(rb_node));
    s->leftchild = Nil;//指向哨兵节点
    s->rightchild = Nil;//指向哨兵节点
    s->color = RED;
    return s;
}
rb_node* MakeRoot(KeyType kx)
{
    rb_node* root = BuyNode();
    root->color = BLACK;
    root->key = kx;
    return root;
}
//左单旋
void RotateLeft(rb_node*& tree, rb_node* ptr)
{
    rb_node* newroot = ptr->rightchild;
    newroot->parent = ptr->parent;
    ptr->rightchild = newroot->leftchild;//1
    if (newroot->leftchild != nullptr)
    {
        newroot->leftchild->parent = ptr;//2
    }
    newroot->leftchild = ptr;
    if (ptr == tree)
    {
        tree = newroot;
    }
    else
    {
        if (ptr->parent->leftchild == ptr)
        {
            ptr->parent->leftchild = newroot;
        }
        else
        {
            ptr->parent->rightchild = newroot;
        }
    }
    ptr->parent = newroot;//3
}
//右单旋
void RotateRight(rb_node*& tree, rb_node* ptr)
{
    rb_node* newroot = ptr->leftchild;//1
    newroot->parent = ptr->parent;//newroot的双亲更新a
    ptr->leftchild = newroot->rightchild;//2 ptr左孩子更新
    if (newroot->rightchild != nullptr)
    {
        newroot->rightchild->parent = ptr;//newroot右孩子的双亲更新b
    }
    newroot->rightchild = ptr;//newroot右孩子更新3
    if (ptr == tree)//如果我本身是根
    {
        tree = newroot;//更新根
    }
    else
    {
        if (ptr->parent->leftchild == ptr)
        {
            ptr->parent->leftchild = newroot;
        }
        else
        {
            ptr->parent->rightchild = newroot;
        }
    }
    ptr->parent = newroot;//ptr双亲更新c
}
void PassRBTree(rb_node*& tree, rb_node* p)
{
    rb_node* _X = nullptr;
    for (; p != tree && p->parent->color == RED;)//p!=tree说明有双亲
    {
        if (p->parent->parent->rightchild == p->parent)//p在p爷爷的右边
        {
            _X = p->parent->parent->leftchild;
            if (_X->color == RED)//p爷爷的左孩子是红色,按照两个图等价交换颜色即可
            {
                _X->color = BLACK;
                p->parent->color = BLACK;
                p->parent->parent->color = RED;
                p = p->parent->parent;
            }
            else//p爷爷的左孩子是黑色,只能旋转了
            {//if条件满足,先右旋再左旋,不满足,就左旋
                if (p->parent->leftchild == p)//p在p爷爷的右边,但是p在p双亲的左边,是一个折线
                {
                    p = p->parent;
                    RotateRight(tree, p);
                }
                p->parent->color = BLACK;//p双亲的颜色变成黑
                p->parent->parent->color = RED;//p爷爷的颜色变成红,
                //就形成了红黑红的形式,然后以黑作为根,将第一个红左单旋转下来
                RotateLeft(tree, p->parent->parent);//左单旋
            }
        } 
        else//pa在p双亲的双亲的左边
        {
            _X = p->parent->parent->rightchild;
            if (_X->color == RED)//p爷爷的右孩子是红色,按照两个图等价交换颜色即可
            {
                _X->color = BLACK;
                p->parent->color = BLACK;
                p->parent->parent->color = RED;
                p = p->parent->parent;
            }
            else//p爷爷的左孩子是黑色,只能旋转了
            {//if条件满足,先左旋再右旋,不满足,就右旋
                if (p->parent->rightchild == p)//p在p爷爷的左边,但是p在p双亲的右边,是一个折线
                {
                    p = p->parent;
                    RotateRight(tree, p);
                }
                p->parent->color = BLACK;//p双亲的颜色变成黑
                p->parent->parent->color = RED;//p爷爷的颜色变成红,
                //就形成了红黑红的形式,然后以黑作为根,将第一个红左单旋转下来
                RotateRight(tree, p->parent->parent);//右单旋
            }
        }
    }
    tree->color = BLACK;//退出以后保证根是黑色
}
bool Insert(rb_node*& tree, KeyType kx)
{
    if (tree == nullptr)
    {
        tree = MakeRoot(kx);
        return true;
    }
    rb_node* pa = nullptr;
    rb_node* p = tree;
    while (p != nullptr && p->key != kx)
    {
        pa = p;
        p = kx < p->key ? p->leftchild : p->rightchild;
    }
    if (p != nullptr && p->key == kx)return false;//如果数据重复的话,返回false
    p = BuyNode();
    p->key = kx;
    p->parent = pa;
    if (kx < pa->key)
    {
        pa->leftchild = p;
    }
    else
    {
        pa->rightchild = p;
    }
    PassRBTree(tree, p);
    return true;
}
int main()
{
    int ar[] = { 16,3,7,11,9,26,18,14,15 };
    AVLTree root = nullptr;
    for (auto& x : ar)
    {
        cout << Insert(root, x) << endl;
    }
    InOrder(root);
    cout << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
红黑树是一种自平衡的二叉搜索树,常用于实现关联容器map。 下面是C++代码示例,实现了一个红黑树类,可以用于实现map: ```c++ #include <iostream> using namespace std; enum Color {RED, BLACK}; template<typename K,typename V> class RBNode { public: K key; V value; Color color; RBNode<K,V> *left, *right, *parent; RBNode(): color(RED), left(nullptr), right(nullptr), parent(nullptr) {} RBNode(K k, V v): color(RED), key(k), value(v), left(nullptr), right(nullptr), parent(nullptr) {} RBNode(K k, V v, Color c): color(c), key(k), value(v), left(nullptr), right(nullptr), parent(nullptr) {} }; template<typename K,typename V> class RBTree { public: RBTree(); ~RBTree(); bool empty() const; int size() const; void clear(); void insert(const K& key,const V& value); bool find(const K& key); void remove(const K& key); void printTree() const; private: RBNode<K,V>* root; int count; void rotateLeft(RBNode<K,V>* node); void rotateRight(RBNode<K,V>* node); void fixup(RBNode<K,V>* node); RBNode<K,V>* minimum(RBNode<K,V>* node); void transplant(RBNode<K,V>* u, RBNode<K,V>* v); void removeNode(RBNode<K,V>* node); }; template<typename K,typename V> RBTree<K,V>::RBTree(): root(nullptr), count(0) {} template<typename K,typename V> RBTree<K,V>::~RBTree() { clear(); } template<typename K,typename V> bool RBTree<K,V>::empty() const { return count == 0; } template<typename K,typename V> int RBTree<K,V>::size() const { return count; } template<typename K,typename V> void RBTree<K,V>::clear() { while (root != nullptr) { removeNode(root); } count = 0; } template<typename K,typename V> void RBTree<K,V>::rotateLeft(RBNode<K,V>* node) { RBNode<K,V>* r = node->right; node->right = r->left; if (r->left != nullptr) r->left->parent = node; r->parent = node->parent; if (node->parent == nullptr) root = r; else if (node == node->parent->left) node->parent->left = r; else node->parent->right = r; r->left = node; node->parent = r; } template<typename K,typename V> void RBTree<K,V>::rotateRight(RBNode<K,V>* node) { RBNode<K,V>* l = node->left; node->left = l->right; if (l->right != nullptr) l->right->parent = node; l->parent = node->parent; if (node->parent == nullptr) root = l; else if (node == node->parent->right) node->parent->right = l; else node->parent->left = l; l->right = node; node->parent = l; } template<typename K,typename V> void RBTree<K,V>::fixup(RBNode<K,V>* node) { while (node->parent != nullptr && node->parent->color == RED) { if (node->parent == node->parent->parent->left) { RBNode<K,V>* uncle = node->parent->parent->right; if (uncle != nullptr && uncle->color == RED) { node->parent->color = BLACK; uncle->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else { if (node == node->parent->right) { node = node->parent; rotateLeft(node); } node->parent->color = BLACK; node->parent->parent->color = RED; rotateRight(node->parent->parent); } } else { RBNode<K,V>* uncle = node->parent->parent->left; if (uncle != nullptr && uncle->color == RED) { node->parent->color = BLACK; uncle->color = BLACK; node->parent->parent->color = RED; node = node->parent->parent; } else { if (node == node->parent->left) { node = node->parent; rotateRight(node); } node->parent->color = BLACK; node->parent->parent->color = RED; rotateLeft(node->parent->parent); } } } root->color = BLACK; } template<typename K,typename V> void RBTree<K,V>::insert(const K& key,const V& value) { RBNode<K,V>* node = new RBNode<K,V>(key, value); RBNode<K,V>* p = nullptr; RBNode<K,V>* q = root; while (q != nullptr) { p = q; if (node->key < q->key) q = q->left; else q = q->right; } node->parent = p; if (p == nullptr) root = node; else if (node->key < p->key) p->left = node; else p->right = node; count++; fixup(node); } template<typename K,typename V> bool RBTree<K,V>::find(const K& key) { RBNode<K,V>* node = root; while (node != nullptr) { if (key == node->key) return true; else if (key < node->key) node = node->left; else node = node->right; } return false; } template<typename K,typename V> void RBTree<K,V>::transplant(RBNode<K,V>* u, RBNode<K,V>* v) { if (u->parent == nullptr) root = v; else if (u == u->parent->left) u->parent->left = v; else u->parent->right = v; if (v != nullptr) v->parent = u->parent; } template<typename K,typename V> void RBTree<K,V>::removeNode(RBNode<K,V>* node) { if (node == nullptr) return; RBNode<K,V>* p = node->parent; bool isLeft = (p != nullptr && node == p->left); if (node->left == nullptr) { transplant(node, node->right); } else if (node->right == nullptr) { transplant(node, node->left); } else { RBNode<K,V>* s = minimum(node->right); RBNode<K,V>* sp = s->parent; isLeft = (s->parent != nullptr && s == s->parent->left); if (s->parent != node) { transplant(s, s->right); s->right = node->right; s->right->parent = s; } transplant(node, s); s->left = node->left; s->left->parent = s; s->color = node->color; } delete node; count--; if (isLeft) fixup(p->left); else fixup(p->right); } template<typename K,typename V> void RBTree<K,V>::remove(const K& key) { RBNode<K,V>* z = root; while (z != nullptr) { if (z->key == key) { removeNode(z); return; } else if (key < z->key) z = z->left; else z = z->right; } } template<typename K,typename V> RBNode<K,V>* RBTree<K,V>::minimum(RBNode<K,V>* node) { while (node->left != nullptr) node = node->left; return node; } template<typename K,typename V> void inOrder(RBNode<K,V>* node) { if (node == nullptr) return; if (node->left != nullptr) inOrder(node->left); cout << node->key << "(" << (node->color == RED ? "RED" : "BLACK") << ") "; if (node->right != nullptr) inOrder(node->right); } template<typename K,typename V> void RBTree<K,V>::printTree() const { inOrder(root); cout << endl; } int main() { RBTree<int,int> tree; tree.insert(1,2); tree.insert(2,3); tree.insert(3,4); tree.insert(4,5); tree.insert(5,6); tree.printTree(); cout << tree.find(3) << endl; tree.remove(3); tree.printTree(); return 0; } ``` 该示例中包含了插入、查找、删除等基本操作,并支持输出红黑树中所有节点及其颜色,可以用于验证红黑树的正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值