红与黑之歌,map与set的底层----红黑树(自实现)

引子:

我们在学习avl搜索二叉树时,知道avl是高度差不超过1的,因此是“绝对平衡的”,那有没有一种“接近平衡”的树呢?让它在这方面轻松一点,更加高效一点?答案是有的,set与map的底层就给出了答案--红黑树,红黑树是一种自平衡的二叉搜索树,它在计算机科学中被广泛使用,特别是在需要频繁插入和删除操作的数据结构中。红黑树的名称来源于它的节点颜色,可以是红色或黑色。这种数据结构能够保证在任何情况下,从根到叶子的最长路径不会超过最短路径的两倍长。

红黑树的性质:

1. 每个结点不是红色就是黑色

2. 根节点是黑色的 

3. 如果一个节点是红色的,则它的两个孩子结点是黑色的 

4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点 

5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

注意:红黑树的这些特性确保了树的平衡性,查找操作的最坏情况时间复杂度能够保持在O(log n)。红黑树常用于实现关联数组,如C++ STL中的mapset。

红黑树插入的三种情况:

前提:新节点的默认颜色是红色,cur为当前节点,p为父节点,g为祖父节点,u为叔叔节点

本人觉得情况二和情况三是在情况一的变化后形成的,因为在情况二和情况三中,cur的颜色为红,不可能为新增节点来得,大家可自行思考

情况一: cur为红,p为红,g为黑,u存在且为红

图:只给出一种情况,如有左右旋,请情况自行考虑

解决方式:将p,u改为黑,g改为红,然后把g当成cur,继续向上调整

情况二: cur为红,p为红,g为黑,u不存在/u存在且为黑

图:只给出一种情况,如有左右旋,请情况自行考虑

解决方式:p为g的左孩子,cur为p的左孩子,则进行右单旋转;相反, p为g的右孩子,cur为p的右孩子,则进行左单旋转 p、g变色--p变黑,g变红

情况三: cur为红,p为红,g为黑,u不存在/u存在且为黑

图:只给出一种情况,如有左右旋,请情况自行考虑

解决方式:p为g的左孩子,cur为p的右孩子,则针对p做左单旋转;相反, p为g的右孩子,cur为p的左孩子,则针对p做右单旋转 则转换成了情况2

自实现代码:

#pragma once
#include<iostream>
#include<set>
using namespace std;

enum Color
{
    RED,
    BLACK
};


template<class T>
class RBTreeNode
{
public:
    T _Data;
    RBTreeNode* _left;
    RBTreeNode* _parent;
    RBTreeNode* _right;
    Color _col;

    RBTreeNode(const T&data)
        :_left(nullptr)
        ,_right(nullptr)
        ,_parent(nullptr)
        ,_Data(data)
    {}
};

//迭代器
template<class T>
class RBTreeIterator
{
public:
    typedef RBTreeNode<T> Node;
    typedef RBTreeIterator<T> self;
    Node* _node;
    Node* _root;

    RBTreeIterator(Node*node,Node*root)
        :_node(node)
        ,_root(root)
    {}

    self& operator++()
    {
        Node* leftMost = _node->_right;

        if (_node->_right)
        {
            leftMost = leftMost->_left;
            while (leftMost)
            {
                leftMost = leftMost->_left;
            }
            _node = leftMost;
        }
        else
        {
            Node* current = _node;
            Node* parent = _node->_parent;
            
            if (parent && parent->_right == current)
            {
                /*parent = parent->_parent;
                cur = parent;*/
                current = parent;
                parent = parent->_parent;
            }
            _node = parent;
        }
        return *this;
    }

    self& operator--()
    {
        if (_node == nullptr) 
        {
            //找最右节点
            Node* rightMost = _root;
            while (rightMost && rightMost->_right)
            {
                rightMost = rightMost->_right;
            }

            _node = rightMost;
        }
        else if (_node->_left)
        {
            Node* rightMost = _node->_left;
            while (rightMost->_right)
            {
                rightMost = rightMost->_right;
            }

            _node = rightMost;
        }
        else
        {
            Node* cur = _node;
            Node* parent = cur->_parent;
            while (parent && cur == parent->_left)
            {
                cur = parent;
                parent = cur->_parent;
            }

            _node = parent;

        }

        return *this;
    }


    T& operator*()
    {
        return _node->_Data;
    }

    bool operator!= (const self& s)
    {
        return _node != s._node;
    }

    bool operator== (const self& s)
    {
        return _node == s._node;
    }
};

//红黑树的实现
template<class K,class T,class K_of_T>
class RBTree

public:
    typedef RBTreeNode<T> Node;
    typedef RBTreeIterator<T> iterator;

    RBTree() = default;

    //构造函数
    RBTree(const T&root)
        :_root(root)
    {}

    //拷贝构造函数,树形节点要一个一个拷贝
    RBTree(const RBTree& h)
    {
        _root = copy(h._root);
    }

    //重载=
    RBTree& operator=(RBTree h)
    {
        swap(_root, h._root);
        return *this;
    }

    //析构函数,注意开辟了空间后,对于树形结构的节点要一个一个删除
    ~RBTree()
    {
        Destory(_root);
        _root = nullptr;
    }

    iterator Begin()
    {
        Node* leftMost = _root;
        while (leftMost && leftMost->_left)
        {
            leftMost = leftMost->_left;
        }
        return iterator(leftMost,_root);
    }

    iterator End()
    {
        return iterator(nullptr,_root);
    }

    //寻找
    Node* Find(const K& key)
    {
        K_of_T kot;
        Node* cur = _root;
        while (cur)
        {
            if (kot(cur->_Data) < key)
            {
                cur = cur->_right;
            }
            else if (kot(cur->_Data) > key)
            {
                cur = cur->_left;
            }
            else
            {
                return cur;
            }
        }

        return nullptr;
    }

    //插入
    pair<iterator,bool>insert(const T& data)
    {
        //空树新增节点,也是红黑树
        Node* root = _root;
        if (root == nullptr)
        {
            root = new Node(data);
            _root = root;
            _root->_col = BLACK;
            return make_pair(iterator(_root, _root), true);
        }

        //红黑树大逻辑
        K_of_T kot;
        Node* cur = _root;
        Node* parent = nullptr;

        //要先找到,插入位置
        while (cur)
        {
            if (kot(data) < kot(cur->_Data))
            {
                parent = cur;
                cur = cur->_left;
            }
            else if (kot(data) > kot(cur->_Data))
            {
                parent = cur;
                cur = cur->_right;
            }
            else
            {
               return make_pair(iterator(cur, _root), false);
            }
        }

        cur = new Node(data);
        // 新增节点。颜色红色给红色
        cur->_col = RED;
        Node* newNode = cur;
        if (kot(parent->_Data) < kot(data))
        {
            parent->_right = cur;
        }
        else
        {
            parent->_left = cur;
        }
        cur->_parent = parent;

        //更改颜色
        //现在cur为新增节点
        while (parent && parent->_col==RED)
        {
            Node* grandfather = parent->_parent;

            //找出叔叔节点
            if (parent == grandfather->_left)
            {
                Node* uncle = grandfather->_right;
                //情况一
                if (uncle && uncle->_col == RED)
                {
                    parent->_col = BLACK;
                    uncle->_col = BLACK;
                    grandfather->_col = RED;
                    cur = grandfather;
                    parent = cur->_parent;
                }
                else
                {
                    //情况二
                    //    g
                    //  p   u
                    //c
                    if (parent->_left == cur)
                    {
                        RotateR(grandfather);
                        grandfather->_col = RED;
                        parent->_col = BLACK;
                    }
                    else
                    {
                        //情况三
                        //    g
                        //  p   u
                        //    c
                        // 
                        //双旋
                        RotateL(parent);
                        RotateR(grandfather);

                        //注意cur与parent调了一下位置
                        cur->_col = BLACK;
                        grandfather->_col = RED;
                    }
                    break;
                }
            }
            else
            {
                Node* uncle = grandfather->_left;
                //情况一
                if (uncle && uncle->_col == RED)
                {
                    parent->_col = BLACK;
                    uncle->_col = BLACK;
                    grandfather->_col = RED;
                    cur = grandfather;
                    parent = cur->_parent;
                }
                else
                { 
                    //情况二
                    //    g
                    //  u   p
                    //        c
                    if (cur == parent->_right)
                    {
                        RotateL(grandfather);
                        grandfather->_col = RED;
                        parent->_col = BLACK;
                    }
                    //情况三
                    //    g
                    //  u   p
                    //    c    
                    else
                    {
                        RotateR(parent);
                        RotateL(grandfather);
                        cur->_col = BLACK;
                        grandfather->_col = RED;
                    }
                    break;
                }
            }
        }

        //确保根节点为黑的
        _root->_col = BLACK;
        return make_pair(iterator(newNode, _root), true);
    }

    int Height()
    {
        return _Height(_root);
    }

    int Size()
    {
        return _Size(_root);
    }

    //中序有序,避免了_root是内部private的加密
    void _InOrder()
    {
        _InOrder(_root);

        cout << endl;
    }
    
    //进行检验
    bool IsBalance()
    {
        //空树也是红黑树
        if (_root == nullptr)
            return true;

        //根节点是黑的
        if (_root->_col == RED)
        {
            return false;
        }

        // 每条路径上的黑节点数目一样
        int refNum = 0;
        Node* cur = _root;
        while (cur)
        {
            if (cur->_col == BLACK)
            {
                ++refNum;
            }

            cur = cur->_left;
        }

        return Check(_root, 0, refNum);
    }


private:

    bool Check(Node* root, int blackNum, const int refNum)
    {
        if (root == nullptr)
        {
            //cout << blackNum << endl;
            if (refNum != blackNum)
            {
                cout << "存在黑色节点的数量不相等的路径" << endl;
                return false;
            }

            return true;
        }

        //不能有连续的红节点
        if (root->_col == RED && root->_parent->_col == RED)
        {
            cout << root->_kv.first << "存在连续的红色节点" << endl;
            return false;
        }

        if (root->_col == BLACK)
        {
            blackNum++;
        }

        return Check(root->_left, blackNum, refNum)
            && Check(root->_right, blackNum, refNum);
    }

    //计算有效的节点
    int _Size(Node* root)
    {
        return root == nullptr ? 0 : _Size(root->_left) + _Size(root->_right) + 1;
    }

    //计算树的高度,利用递归
    int _Height(Node* root)
    {
        if (root == nullptr)
            return 0;

        int leftHeight = _Height(root->_left);
        int rightHeight = _Height(root->_right);

        return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
    }

    //中序遍历
    void _InOrder(Node* root)
    {
        if (root == nullptr)
        {
            return;
        }
        //左根右;
        _InOrder(root->_left);
        cout << root->_kv.first << " :" << root->_kv.second << " ";
        _InOrder(root->_right);
    }

    //左旋
    void RotateL(Node* parent)
    {
        Node* subR = parent->_right;
        Node* subRL = subR->_left;

        parent->_right = subRL;
        if (subRL)
            subRL->_parent = parent;

        subR->_left = parent;
        parent->_parent = subR;

        Node* parent_parent = parent->_parent;
        if (parent_parent == nullptr)
        {
            _root = subR;
            parent_parent = nullptr;
        }
        else
        {
            if (parent_parent->_left == parent)
            {
                parent_parent->_left = subR;
            }
            else if (parent_parent->_right == parent)
            {
                parent_parent->_right = subR;
            }
            subR->_parent = parent_parent;
        }
    }

    //右旋
    void RotateR(Node* parent)
    {
        Node* subL = parent->_left;
        Node* subLR = subL->_right;
        parent->_left = subLR;
        if (subLR)
            subLR->_parent = parent;

        subL->_right = parent;
        parent->_parent = subL;

        Node* parent_parent = parent->_parent;
        if (parent_parent == nullptr)
        {
            _root = subL;
            parent_parent = nullptr;
        }
        else
        {
            if (parent_parent->_left == parent)
            {
                parent_parent->_left = subL;
            }
            else if (parent_parent->_right == parent)
            {
                parent_parent->_right = subL;
            }
            subL->_parent = parent_parent;
        }
    }

    //销毁
    void Destory(Node* root)
    {
        if (root == nullptr)
        {
            return;
        }
        Destory(root->_left);
        Destory(root->_right);
        Destory(root->_parent);
        delete root;
    }

    //拷贝
    Node* copy(const Node*& root)
    {
        if (root == nullptr)
        {
            return nullptr;
        }
        Node* temp = new Node(root->_kv);
        temp->_left = copy(root->_left);
        temp->_right = copy(root->_right);
        temp->_parent = copy(root->_parent);
        return temp;
    }

    Node* _root = nullptr;
};


 

结语:本文已经实现了一部分map与set的接口,下集我们相约map与set封装,哈希等好知识点,感谢大家的支持!
以下是一些接口:

namespace my_map
{

	template<class K, class V>
	class map
	{
	public:
		struct K_of_T
		{
			const K& operator()(const pair<K, V>& kv)
			{
				return kv.first;
			}
		};
		typedef typename RBTree<K, K, K_of_T>::iterator iterator;
		iterator begin()
		{
			return _t.Begin();
		}

		iterator end()
		{
			return _t.End();
		}
		pair<iterator, bool>Insert(const pair<K, V>& kv)
		{
			_t.Insert(kv);
		}
	private:
		RBTree<K, pair<K, V>, K_of_T> _t;
	};
}
namespace my_set
{
	template<class K>
	class set
	{
	public:
		struct K_of_T
		{
			const K& operator()(const K& key)
			{
				return key;
			}
		};
		typedef typename RBTree<K, K, K_of_T>::iterator iterator;

		iterator begin()
		{
			return _t.Begin();
		}

		iterator end()
		{
			return _t.End();
		}

		pair<iterator, bool>insert(const K& key)
		{
			return _t.insert(key);
		}
	private:
		RBTree<K, K, K_of_T> _t;
	};
}

  • 19
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值