c++构建红黑树

#include <iostream>
#include<stack>
using namespace std;

/*
    1:红黑树结点有三个指针域,分别指向父节点,左孩子,右孩子
    有一个数据域,有一个标志域(红,黑),提供一个列表初始化构造函数

    2:构造一棵红黑树:
        2.1:先构造一棵二叉排序树;
        2.2:分类调整

    3:parent为红时调整
        3.1  uncle存在且为红:
            爷变红,父叔变黑,递归向上
        3.2  uncle不存在或uncle存在且为黑
            3.2.1  子在父爷右侧(单向左旋,爷变红,父变黑)
            3.2.2  子在父爷左侧(单向右旋,爷变红,父变黑)
            3.2.3  子在爷右父左(先右旋后左旋,爷变红,子变黑)
            3.2.4  子在爷右父左(先左旋后右旋,爷变红,子变黑)

    4.插入函数最后要将root设置为黑色

*/


enum Color {RED,BLACK};
typedef int datatype; 

typedef struct Node {
    datatype _data;
    Node* _left;
    Node* _right;
    Node* _parent;
    Color _col;

    //列表初始化构造函数
    Node(datatype data):_data(data),_left(nullptr),_right(nullptr),_parent(nullptr),_col(RED){}

}Node;


struct RBTree {
    public:
        Node* _root=nullptr;
    public:

        //左单旋
        void lrotate(Node* T)
        {
            Node* x = T->_right;
            Node* y = x->_left;

            T->_right = y;
            if (y)
                y->_parent = T;

            //先保存一下T->_T,因为下面会改它
            Node* pT = T->_parent;

            x->_left = T;
            T->_parent = x;

            //若pT为空则证明旋转的是一整棵树,因为根结点的_parent为空
            if (pT == nullptr)
            {
                //x是新的根
                _root = x;
                _root->_parent = nullptr;
            }
            //若pT不为空,则证明旋转的是子树,T上面还有结点
            else
            {
                //让pT指向子树旋转之后新的根
                if (pT->_left == T)
                {
                    pT->_left = x;
                }
                else
                {
                    pT->_right = x;
                }
                //同时也让新的根指向pT
                x->_parent = pT;
            }
        }

        //右单旋
        void rrotate(Node* T)
        {
            Node* x = T->_left;
            Node* y = x->_right;

            //旋转并更新_T指针
            T->_left = y;
            if (y)
                y->_parent = T;

            //先保存一下T->_parent,因为下面会改它
            Node* pT = T->_parent;

            //旋转并更新_T指针
            x->_right = T;
            T->_parent = x;

            //若T等于_root则证明旋转的是一整棵树(这也是一种判断方法)
            if (T == _root)
            {
                _root = x;
                x->_parent = nullptr;
            }
            else
            {
                //让pT指向子树旋转之后新的根
                if (T == pT->_left)
                {
                    pT->_left = x;
                }
                else
                {
                    pT->_right = x;
                }
                //同时也让新的根指向pT
                x->_parent = pT;
            }
        }

        //插入
        bool insert(datatype data) {
            if (_root == nullptr) {
                _root = new Node(data);
                _root->_col = BLACK;
            }
            Node* parent = nullptr;
            Node* cur = _root;
            while (cur) {
                if (data < cur->_data) {
                    parent = cur;
                    cur = cur->_left;
                }
                else if (data > cur->_data) {
                    parent = cur;
                    cur = cur->_right;
                }
                else {
                    return parent?false:true; //parent为空时,插入的是根结点,返回true,插入成功
                }
            }
            //到这里时cur为空
            cur = new Node(data);
            cur->_parent = parent;
            if (data < parent->_data) {
                parent->_left = cur;
            }
            if (data > parent->_data) {
                parent->_right = cur;
            }

            //插入完成,检查
            while (parent && parent->_col == RED)
            {
                Node* g = parent->_parent;
                if (parent == g->_left)  //左边插入
                {
                    Node* uncle = g->_right;
                    if (uncle && uncle->_col == RED) {  //叔存在且为红
                        g->_col = RED;
                        parent->_col = BLACK;
                        uncle->_col = BLACK;

                        cur = g;
                        parent = cur->_parent; //向上递归
                    }
                    else {  //叔不存在或为黑
                        if (cur == parent->_left) {  //属于LL,单右旋
                            rrotate(g);
                            g->_col = RED;
                            parent->_col = BLACK;
                        }
                        else {  //属于LR,先左旋后右旋
                            lrotate(parent);
                            rrotate(g);
                            cur->_col = BLACK;
                            g->_col = RED;
                        }
                        break;
                    }
                }
                else  //右边插入parent==g->_right
                {
                    Node* uncle = g->_left;
                    if (uncle && uncle->_col == RED) //叔存在且为红
                    {
                        g->_col = RED;
                        parent->_col = BLACK;
                        uncle->_col = BLACK;
                        cur = g;
                        parent = cur->_parent;
                    }
                    else {//叔不存在或存在且为黑
                        if (cur == parent->_right) {   //属于RR,单向左旋
                            lrotate(g);
                            g->_col = RED;
                            parent->_col = BLACK;
                        }
                        else {  //属于RL,先右旋后左旋
                            rrotate(parent);
                            lrotate(g);
                            cur->_col = BLACK;
                            g->_col = RED;
                        }
                        break;
                    }
                }

            }//while,在while里面检查,旋转,变色
            _root->_col = BLACK;
            return true;
        }//insert

};//RBTree


//先序遍历
void prePrint(Node* T) {
    if (T) {
        cout << T->_data << " ";
        prePrint(T->_left);
        prePrint(T->_right);
    }
}

//中序遍历二叉排序树,借助一个栈
void inPrint(Node* T) {
    stack<Node*> s;
    while (T || !s.empty()) {
        if (!T) {//T为空
            Node* p = s.top();
            cout << p->_data << " ";
            T = p->_right;
            s.pop();
        }
        else {
            s.push(T);
            T = T->_left;
        }
    }
}

void main() {
    RBTree tree;
    int x[] = { 5,8,6,4,7,2,1,64,21,15,13,14,10,12 };
    int len = sizeof(x) / sizeof(x[0]);
    for (int i = 0;i < len;i++) {
        tree.insert(x[i]);
    }
    prePrint(tree._root);
    cout << endl;
    inPrint(tree._root);
    system("pause");
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值