用一棵红黑树同时封装出map和set

简介: 再完成上面的代码后,我们的底层代码已经完成了,这时候已经是一个底层STL的红黑树了,已经已符合库里面的要求了,这时候我们是需要给他穿上对应的“衣服”,比如穿上set的“衣服”,那么这个穿上set的“衣服”,那么他就符合库里面set的要求了,同样map一样,这时候我们就需要实现set与map了。因此,上层容器map需要向底层红黑树提供一个仿函数,用于获取T当中的键值Key,这样一来,当底层红黑树当中需要比较两个结点的键值时,就可以通过这个仿函数来获取T当中的键值了。我们就可以使用仿函数了。


目录

红黑树源代码
下面我们将对一棵KV模型的红黑树进行封装,同时模拟实现出C++STL库当中的map和set,所用到的红黑树源代码如下:

pragma once

include

include

include

using namespace std;
enum Colour
{
RED,
BLACK,
};

template
struct RBTreeNode
{
RBTreeNode _left;
RBTreeNode
_right;
RBTreeNode* _parent;
T _data;
Colour _col;

RBTreeNode(const T& data)
    : _left(nullptr)
    , _right(nullptr)
    , _parent(nullptr)
    , _data(data)
    , _col(RED)
{}

};

template
struct TreeIterator
{
typedef RBTreeNode Node;
typedef
TreeIterator Self;
Node* _node;

__TreeIterator(Node* node)
    :_node(node)
{}
Ref operator*()
{
    return _node->_data;
}
Ptr operator->()
{
    return &_node->_data;
}
Self& operator--()
{
    //走的是中序  左 根 右
    if (_node->_left)
    {
        //左不为空,下一个就是左子树的最右
        Node* cur = _node->_left;
        while (cur->_right)
        {
            cur = cur->_right;
        }
        _node = cur;
    }

    else
    {
        //左为空,没根找孩子是父亲右的那个祖先
        Node* cur = _node;
        Node* parent = cur->_parent;
        while (parent && cur == parent->_left)
        {
            cur = parent;
            parent = parent->_parent;
        }
        _node = parent;
    }

    return *this;
}
Self& operator++()
{
    //走的是中序  左 根 右
    if (_node->_right)
    {
        //右子树不为空,下一个就是右子树的最左结点
        Node* cur = _node->_right;
        while (cur->_left)
        {
            cur = cur->_left;
        }

        _node = cur;
    }

    else
    {
        //右子树为空,it所在全已访问完,下一个就是往上找左(孩子是父亲左的那个祖先)
        Node* cur = _node;
        Node* parent = cur->_parent;
        while (parent && cur == parent->_right)
        {
            cur = parent;
            parent = parent->_parent;
        }

        _node = parent;
    }

    return *this;
}
bool operator!=(const Self& s)
{
    return _node != s._node;
}
bool operator==(const Self& s)
{
    return _node == s._node;
}

};

template
class RBTree
{
typedef RBTreeNode Node;
public:
typedef TreeIterator iterator;
typedef
TreeIterator const_iterator;
iterator begin()
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}

    return iterator(cur);
}    
iterator end()
{
    return iterator(nullptr);
}
const_iterator begin() const
{
    Node* cur = _root;
    while (cur && cur->_left)
    {
        cur = cur->_left;
    }

    return const_iterator(cur);
}
const_iterator end() const
{
    return const_iterator(nullptr);
}
pair<Node*, bool> Insert(const T& data)
{
    if (_root == nullptr)
    {
        _root = new Node(data);

        _root->_col = BLACK;
        return make_pair(_root, true);;
    }

    Node* parent = nullptr;
    Node* cur = _root;

    while (cur)
    {
        if (cur->_data < data)
        {
            parent = cur;
            cur = cur->_right;
        }
        else if (cur->_data > data)
        {
            parent = cur;
            cur = cur->_left;
        }
        else
        {
            return make_pair(cur, false);;
        }
    }

    cur = new Node(data);
    Node* newnode = cur;
    //默认结点颜色为红色

    if (parent->_data < data)
    {
        parent->_right = cur;
        cur->_parent = parent;
    }
    else
    {
        parent->_left = cur;
        cur->_parent = parent;
    }

    while (parent && parent->_col == RED)
    {
        Node* grandfather = parent->_parent;
        //大前提
        //parent在左
        if (parent == grandfather->_left)
        {
            Node* uncle = grandfather->_right;
            //Node* uncle = parent->_right;//错误二
            if (uncle && uncle->_col == RED)
            {
                //情景一:cur->红,parent->红,grandfather->黑,uncle存在且为红
                    //     g
                    //   p   u
                    // c
                    // 
                    //解决:p,u改为黑,g改为红,最后g为红所以,要继续向上调整
                parent->_col = uncle->_col = BLACK;
                grandfather->_col = RED;
                cur = grandfather;
                parent = cur->_parent;
            }
            else
            {
                if (cur == parent->_left)
                {
                    //情景二:cur->红,parent->红,grandfather->黑,uncle不存在/为黑
                        //     g
                        //   p   u
                        // c
                        // 
                    // 解决:对g右单旋,p改为黑,g改为红,最后g为黑所以,直接break
                    RotateR(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                }
                else
                {
                    //情景三:cur->红,parent->红,grandfather->黑,uncle不存在/为黑
                        //       g
                        //   p      u
                        //     c
                    // 解决:对p左单旋,后变为情景二。
                    RotateL(parent);
                    RotateR(grandfather);
                    cur->_col = BLACK;
                    grandfather->_col = RED;
                }
                break;
            }
        }
        else//情景大概反着来
        {
            //1  uncle
            Node* uncle = grandfather->_left;//错误一
            //Node* uncle = parent->_right;//错误一
            if (uncle && uncle->_col == RED)
            {
                parent->_col = uncle->_col = BLACK;
                grandfather->_col = RED;
                cur = grandfather;
                parent = cur->_parent;
            }

            else
            {
                if (cur == parent->_right)//2
                {
                    RotateL(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                }
                else//3
                {
                    RotateR(parent);
                    RotateL(grandfather);
                    cur->_col = BLACK;
                    grandfather->_col = RED;
                }
                break;
            }
        }
    }
    //最后
    _root->_col = BLACK;

    return make_pair(newnode, true);;
}
void RotateL(Node* parent)
{
    Node* subR = parent->_right;
    Node* subRL = subR->_left;

    parent->_right = subRL;
    subR->_left = parent;

    Node* parentParent = parent->_parent;

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

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

        subR->_parent = parentParent;
    }
}

void RotateR(Node* parent)
{
    Node* subL = parent->_left;
    Node* subLR = subL->_right;

    parent->_left = subLR;
    if (subLR)
        subLR->_parent = parent;

    Node* parentParent = parent->_parent;

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

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

        subL->_parent = parentParent;
    }
}

iterator Find(const K& key)
{
    Node* cur = _root;
    KeyOfT kot;
    while (cur)
    {
        if (cur->_data < key)
        {
            cur = cur->_right;
        }
        else if (cur->_data > key)
        {
            cur = cur->_left;
        }
        else
        {
            return iterator(cur);
        }
    }
    return end();
}
void InOrder()
{
    _InOrder(_root);
    cout << endl;
}
void _InOrder(Node* root)
{
    if (root == nullptr)
        return;
    _InOrder(root->_left);
    cout << kof(root->_data) << " ";
    _InOrder(root->_right);
}
bool Check(Node* root, int blacknum, const int refVal)
{
    if (root == nullptr)
    {
        if (refVal != blacknum)
        {
            cout << "存在黑色节点数量不相等的路径" << endl;
            return false;
        }
        return true;
    }
    if (root->_col == RED)
    {
        if (root->_parent->_col == RED)
        {
            cout << "有连续的红色节点" << endl;
            return false;
        }
    }
    if (root->_col == BLACK)
    {
        ++blacknum;
    }
    return Check(root->_left, blacknum, refVal)
        && Check(root->_right, blacknum, refVal);

}
bool IsBalance()
{
    //1:是否存在 红-红 
   //每条路径黑色结点是否相同个数
   //最长的不超过最短的二倍
   //根,叶子为黑
    if (_root == nullptr)
        return true;
    if (_root->_col == RED)
        return false;
    int refVal = 0;
    Node* cur = _root;
    while (cur)
    {
        if (cur->_col == BLACK)
        {
            ++refVal;
        }
        cur = cur->_left;
    }
    int blacknum = 0;
    return Check(_root, blacknum, refVal);
}

private:
Node* _root = nullptr;
};
对于封装,要想看明白这篇文章还是需要把我写的上一篇文章看明白的,上一章的知识就是铺垫知识,是必要的。

模板参数中仿函数的增加
再完成上面的代码后,我们的底层代码已经完成了,这时候已经是一个底层STL的红黑树了,已经已符合库里面的要求了,这时候我们是需要给他穿上对应的“衣服”,比如穿上set的“衣服”,那么这个穿上set的“衣服”,那么他就符合库里面set的要求了,同样map一样,这时候我们就需要实现set与map了。

那么第一个问题就是:

当上层容器是set的时候T就是键值Key,直接用T进行比较即可,但当上层容器是map的时候就不行了,此时我们需要从键值对当中取出键值Key后,再用Key值进行比较。

因此,上层容器map需要向底层红黑树提供一个仿函数,用于获取T当中的键值Key,这样一来,当底层红黑树当中需要比较两个结点的键值时,就可以通过这个仿函数来获取T当中的键值了。

template
class map
{
public:
//仿函数
struct MapKeyOfT
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
//...
private:
RBTree, MapKeyOfT> _t;
};
但是对于底层红黑树来说,它并不知道上层容器是map还是set,因此当需要进行两个结点键值的比较时,底层红黑树都会通过传入的仿函数来获取键值Key,进而进行两个结点键值的比较。

因此,set容器也需要向底层红黑树传入一个仿函数,虽然这个仿函数单独看起来没什么用,但却是必不可少的。

template<class K>
class set
{
public:
    //仿函数
    struct SetKeyOfT 
    {
        const K& operator()(const K& key)
        {
            return key;
        }
    };
private:
    RBTree<K, K, SetKeyOfT> _t;
};

此时,set容器传入底层红黑树的就是set的仿函数,map容器传入底层红黑树的就是map的仿函数。

这样一来,当底层红黑树需要进行两个结点之间键值的比较时,都会通过传入的仿函数来获取相应结点的键值,然后再进行比较,下面以红黑树的查找函数为例:

我们就可以使用仿函数了。

iterator Find(const K& key)
{
    Node* cur = _root;
    KeyOfT kot;
    while (cur)
    {
        if (kot(cur->_data) < key)
        {
            cur = cur->_right;
        }
        else if (kot(cur->_data) > key)
        {
            cur = cur->_left;
        }
        else
        {
            return iterator(cur);
        }
    }
    return end();
}

注意: 所有进行结点键值比较的地方,均需要通过仿函数获取对应结点的键值后再进行键值的比较。

同样我们还需要用同样的方法对insert进行修改,

修改后的代码:

pair Insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);

    _root->_col = BLACK;
    return make_pair(_root, true);;
}

Node* parent = nullptr;
Node* cur = _root;
KeyOfT kot;

while (cur)
{
    if (kot(cur->_data) < kot(data))
    {
        parent = cur;
        cur = cur->_right;
    }
    else if (kot(cur->_data) > kot(data))
    {
        parent = cur;
        cur = cur->_left;
    }
    else
    {
        return make_pair(cur, false);;
    }
}

cur = new Node(data);
Node* newnode = cur;
//默认结点颜色为红色

if (kot(parent->_data) < kot(data))
{
    parent->_right = cur;
    cur->_parent = parent;
}
else
{
    parent->_left = cur;
    cur->_parent = parent;
}

while (parent && parent->_col == RED)
{
    Node* grandfather = parent->_parent;
    //大前提
    //parent在左
    if (parent == grandfather->_left)
    {
        Node* uncle = grandfather->_right;
        //Node* uncle = parent->_right;//错误二
        if (uncle && uncle->_col == RED)
        {
            //情景一:cur->红,parent->红,grandfather->黑,uncle存在且为红
                //     g
                //   p   u
                // c
                // 
                //解决:p,u改为黑,g改为红,最后g为红所以,要继续向上调整
            parent->_col = uncle->_col = BLACK;
            grandfather->_col = RED;
            cur = grandfather;
            parent = cur->_parent;
        }
        else
        {
            if (cur == parent->_left)
            {
                //情景二:cur->红,parent->红,grandfather->黑,uncle不存在/为黑
                    //     g
                    //   p   u
                    // c
                    // 
                // 解决:对g右单旋,p改为黑,g改为红,最后g为黑所以,直接break
                RotateR(grandfather);
                parent->_col = BLACK;
                grandfather->_col = RED;
            }
            else
            {
                //情景三:cur->红,parent->红,grandfather->黑,uncle不存在/为黑
                    //       g
                    //   p      u
                    //     c
                // 解决:对p左单旋,后变为情景二。
                RotateL(parent);
                RotateR(grandfather);
                cur->_col = BLACK;
                grandfather->_col = RED;
            }
            break;
        }
    }
    else//情景大概反着来
    {
        //1  uncle
        Node* uncle = grandfather->_left;//错误一
        //Node* uncle = parent->_right;//错误一
        if (uncle && uncle->_col == RED)
        {
            parent->_col = uncle->_col = BLACK;
            grandfather->_col = RED;
            cur = grandfather;
            parent = cur->_parent;
        }

        else
        {
            if (cur == parent->_right)//2
            {
                RotateL(grandfather);
                parent->_col = BLACK;
                grandfather->_col = RED;
            }
            else//3
            {
                RotateR(parent);
                RotateL(grandfather);
                cur->_col = BLACK;
                grandfather->_col = RED;
            }
            break;
        }
    }
}
//最后
_root->_col = BLACK;

return make_pair(newnode, true);;

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

parent->_right = subRL;
subR->_left = parent;

Node* parentParent = parent->_parent;

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

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

    subR->_parent = parentParent;
}

}

void RotateR(Node parent)
{
Node
subL = parent->_left;
Node* subLR = subL->_right;

parent->_left = subLR;
if (subLR)
    subLR->_parent = parent;

Node* parentParent = parent->_parent;

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

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

    subL->_parent = parentParent;
}

}
修改后的红黑树代码:

pragma once

include

include

include

using namespace std;
enum Colour
{
RED,
BLACK,
};

template
struct RBTreeNode
{
RBTreeNode _left;
RBTreeNode
_right;
RBTreeNode* _parent;
T _data;
Colour _col;

RBTreeNode(const T& data)
    : _left(nullptr)
    , _right(nullptr)
    , _parent(nullptr)
    , _data(data)
    , _col(RED)
{}

};

template
struct TreeIterator
{
typedef RBTreeNode Node;
typedef
TreeIterator Self;
Node* _node;

__TreeIterator(Node* node)
    :_node(node)
{}
Ref operator*()
{
    return _node->_data;
}
Ptr operator->()
{
    return &_node->_data;
}
Self& operator--()
{
    //走的是中序  左 根 右
    if (_node->_left)
    {
        //左不为空,下一个就是左子树的最右
        Node* cur = _node->_left;
        while (cur->_right)
        {
            cur = cur->_right;
        }
        _node = cur;
    }

    else
    {
        //左为空,没根找孩子是父亲右的那个祖先
        Node* cur = _node;
        Node* parent = cur->_parent;
        while (parent && cur == parent->_left)
        {
            cur = parent;
            parent = parent->_parent;
        }
        _node = parent;
    }

    return *this;
}
Self& operator++()
{
    //走的是中序  左 根 右
    if (_node->_right)
    {
        //右子树不为空,下一个就是右子树的最左结点
        Node* cur = _node->_right;
        while (cur->_left)
        {
            cur = cur->_left;
        }

        _node = cur;
    }

    else
    {
        //右子树为空,it所在全已访问完,下一个就是往上找左(孩子是父亲左的那个祖先)
        Node* cur = _node;
        Node* parent = cur->_parent;
        while (parent && cur == parent->_right)
        {
            cur = parent;
            parent = parent->_parent;
        }

        _node = parent;
    }

    return *this;
}
bool operator!=(const Self& s)
{
    return _node != s._node;
}
bool operator==(const Self& s)
{
    return _node == s._node;
}

};

template
class RBTree
{
typedef RBTreeNode Node;
public:
typedef TreeIterator iterator;
typedef
TreeIterator const_iterator;
iterator begin()
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}

    return iterator(cur);
}    
iterator end()
{
    return iterator(nullptr);
}
const_iterator begin() const
{
    Node* cur = _root;
    while (cur && cur->_left)
    {
        cur = cur->_left;
    }

    return const_iterator(cur);
}
const_iterator end() const
{
    return const_iterator(nullptr);
}
pair<Node*, bool> Insert(const T& data)
{
    if (_root == nullptr)
    {
        _root = new Node(data);

        _root->_col = BLACK;
        return make_pair(_root, true);;
    }

    Node* parent = nullptr;
    Node* cur = _root;
    KeyOfT kot;

    while (cur)
    {
        if (kot(cur->_data) < kot(data))
        {
            parent = cur;
            cur = cur->_right;
        }
        else if (kot(cur->_data) > kot(data))
        {
            parent = cur;
            cur = cur->_left;
        }
        else
        {
            return make_pair(cur, false);;
        }
    }

    cur = new Node(data);
    Node* newnode = cur;
    //默认结点颜色为红色

    if (kot(parent->_data) < kot(data))
    {
        parent->_right = cur;
        cur->_parent = parent;
    }
    else
    {
        parent->_left = cur;
        cur->_parent = parent;
    }

    while (parent && parent->_col == RED)
    {
        Node* grandfather = parent->_parent;
        //大前提
        //parent在左
        if (parent == grandfather->_left)
        {
            Node* uncle = grandfather->_right;
            //Node* uncle = parent->_right;//错误二
            if (uncle && uncle->_col == RED)
            {
                //情景一:cur->红,parent->红,grandfather->黑,uncle存在且为红
                    //     g
                    //   p   u
                    // c
                    // 
                    //解决:p,u改为黑,g改为红,最后g为红所以,要继续向上调整
                parent->_col = uncle->_col = BLACK;
                grandfather->_col = RED;
                cur = grandfather;
                parent = cur->_parent;
            }
            else
            {
                if (cur == parent->_left)
                {
                    //情景二:cur->红,parent->红,grandfather->黑,uncle不存在/为黑
                        //     g
                        //   p   u
                        // c
                        // 
                    // 解决:对g右单旋,p改为黑,g改为红,最后g为黑所以,直接break
                    RotateR(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                }
                else
                {
                    //情景三:cur->红,parent->红,grandfather->黑,uncle不存在/为黑
                        //       g
                        //   p      u
                        //     c
                    // 解决:对p左单旋,后变为情景二。
                    RotateL(parent);
                    RotateR(grandfather);
                    cur->_col = BLACK;
                    grandfather->_col = RED;
                }
                break;
            }
        }
        else//情景大概反着来
        {
            //1  uncle
            Node* uncle = grandfather->_left;//错误一
            //Node* uncle = parent->_right;//错误一
            if (uncle && uncle->_col == RED)
            {
                parent->_col = uncle->_col = BLACK;
                grandfather->_col = RED;
                cur = grandfather;
                parent = cur->_parent;
            }

            else
            {
                if (cur == parent->_right)//2
                {
                    RotateL(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                }
                else//3
                {
                    RotateR(parent);
                    RotateL(grandfather);
                    cur->_col = BLACK;
                    grandfather->_col = RED;
                }
                break;
            }
        }
    }
    //最后
    _root->_col = BLACK;

    return make_pair(newnode, true);;
}
void RotateL(Node* parent)
{
    Node* subR = parent->_right;
    Node* subRL = subR->_left;

    parent->_right = subRL;
    subR->_left = parent;

    Node* parentParent = parent->_parent;

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

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

        subR->_parent = parentParent;
    }
}

void RotateR(Node* parent)
{
    Node* subL = parent->_left;
    Node* subLR = subL->_right;

    parent->_left = subLR;
    if (subLR)
        subLR->_parent = parent;

    Node* parentParent = parent->_parent;

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

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

        subL->_parent = parentParent;
    }
}

iterator Find(const K& key)
{
    Node* cur = _root;
    KeyOfT kot;
    while (cur)
    {
        if (kot(cur->_data) < key)
        {
            cur = cur->_right;
        }
        else if (kot(cur->_data) > key)
        {
            cur = cur->_left;
        }
        else
        {
            return iterator(cur);
        }
    }
    return end();
}
void InOrder()
{
    _InOrder(_root);
    cout << endl;
}
void _InOrder(Node* root)
{
    if (root == nullptr)
        return;
    _InOrder(root->_left);
    cout << kof(root->_data) << " ";
    _InOrder(root->_right);
}
bool Check(Node* root, int blacknum, const int refVal)
{
    if (root == nullptr)
    {
        if (refVal != blacknum)
        {
            cout << "存在黑色节点数量不相等的路径" << endl;
            return false;
        }
        return true;
    }
    if (root->_col == RED)
    {
        if (root->_parent->_col == RED)
        {
            cout << "有连续的红色节点" << endl;
            return false;
        }
    }
    if (root->_col == BLACK)
    {
        ++blacknum;
    }
    return Check(root->_left, blacknum, refVal)
        && Check(root->_right, blacknum, refVal);

}
bool IsBalance()
{
    //1:是否存在 红-红 
   //每条路径黑色结点是否相同个数
   //最长的不超过最短的二倍
   //根,叶子为黑
    if (_root == nullptr)
        return true;
    if (_root->_col == RED)
        return false;
    int refVal = 0;
    Node* cur = _root;
    while (cur)
    {
        if (cur->_col == BLACK)
        {
            ++refVal;
        }
        cur = cur->_left;
    }
    int blacknum = 0;
    return Check(_root, blacknum, refVal);
}

private:
Node* _root = nullptr;
};
set的模拟实现
同样对于set的代码还需要添加上各个底层实现的功能,比如insert,find,迭代器begin与end......

其模拟实现也就很简单了,其中的成员函数都是调用底层红黑树的对应接口就行了,只不过需要注意将插入函数和查找函数返回值当中的结点指针改为迭代器即可。

template<class K>
class set
{
public:
    //仿函数
    struct SetKeyOfT 
    {
        const K& operator()(const K& key)
        {
            return key;
        }
    };
    typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
    typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
    iterator begin() const
    {
        return _t.begin();
    }
    iterator end() const
    {
        return _t.end();
    }
    pair<iterator, bool> insert(const K& key)
    {
        return _t.Insert(key);
    }
    bool IsBalance()
    {
        return _t.IsBalance();
    }
private:
    RBTree<K, K, SetKeyOfT> _t;
};

map的模拟实现
map的模拟实现也是相同的道理,其成员函数也是调用底层红黑树的对应接口,但对于map来说,除了将插入函数和查找函数返回值当中的结点指针改为迭代器之外,还需要实现[]运算符的重载函数。

template
class map
{
public:
//仿函数
struct MapKeyOfT
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
// 对类模板取内嵌类型,加typename告诉编译器这里是类型
typedef typename RBTree, MapKeyOfT>::iterator iterator;
typedef typename RBTree, MapKeyOfT>::const_iterator const_iterator;
iterator begin() const
{
return _t.begin();
}
iterator end() const
{
return _t.end();
}
pair insert(const pair& kv)
{
return _t.Insert(kv);
}
V& operator
{
pair < iterator, bool> ret = insert(make_pair(key, V()));//默认构造为0
//V():在这里,V() 是一个临时创建的 V 类型的对象。
// 它使用 V 类型的默认构造函数创建一个默认的值对象。
// 这样做的目的是为了确保即使映射中没有该键,
// 也能够返回一个默认构造的值的引用,以便在插入新键值对时,
// 通过返回引用,可以直接为新键关联一个默认构造的值。
return ret.first->second;
}
bool IsBalance()
{
return _t.IsBalance();
}
private:
RBTree, MapKeyOfT> _t;
};
封装完成后的代码
虽然封装过程已经阐述完毕了,但在代码更改过程中还是有许多细节的,下面给出完整封装后的代码。

红黑树的代码

pragma once

include

include

include

using namespace std;
enum Colour
{
RED,
BLACK,
};

template
struct RBTreeNode
{
RBTreeNode _left;
RBTreeNode
_right;
RBTreeNode* _parent;
T _data;
Colour _col;

RBTreeNode(const T& data)
    : _left(nullptr)
    , _right(nullptr)
    , _parent(nullptr)
    , _data(data)
    , _col(RED)
{}

};

template
struct TreeIterator
{
typedef RBTreeNode Node;
typedef
TreeIterator Self;
Node* _node;

__TreeIterator(Node* node)
    :_node(node)
{}
Ref operator*()
{
    return _node->_data;
}
Ptr operator->()
{
    return &_node->_data;
}
Self& operator--()
{
    //走的是中序  左 根 右
    if (_node->_left)
    {
        //左不为空,下一个就是左子树的最右
        Node* cur = _node->_left;
        while (cur->_right)
        {
            cur = cur->_right;
        }
        _node = cur;
    }

    else
    {
        //左为空,没根找孩子是父亲右的那个祖先
        Node* cur = _node;
        Node* parent = cur->_parent;
        while (parent && cur == parent->_left)
        {
            cur = parent;
            parent = parent->_parent;
        }
        _node = parent;
    }

    return *this;
}
Self& operator++()
{
    //走的是中序  左 根 右
    if (_node->_right)
    {
        //右子树不为空,下一个就是右子树的最左结点
        Node* cur = _node->_right;
        while (cur->_left)
        {
            cur = cur->_left;
        }

        _node = cur;
    }

    else
    {
        //右子树为空,it所在全已访问完,下一个就是往上找左(孩子是父亲左的那个祖先)
        Node* cur = _node;
        Node* parent = cur->_parent;
        while (parent && cur == parent->_right)
        {
            cur = parent;
            parent = parent->_parent;
        }

        _node = parent;
    }

    return *this;
}
bool operator!=(const Self& s)
{
    return _node != s._node;
}
bool operator==(const Self& s)
{
    return _node == s._node;
}

};

template
class RBTree
{
typedef RBTreeNode Node;
public:
typedef TreeIterator iterator;
typedef
TreeIterator const_iterator;
iterator begin()
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}

    return iterator(cur);
}    
iterator end()
{
    return iterator(nullptr);
}
const_iterator begin() const
{
    Node* cur = _root;
    while (cur && cur->_left)
    {
        cur = cur->_left;
    }

    return const_iterator(cur);
}
const_iterator end() const
{
    return const_iterator(nullptr);
}
pair<Node*, bool> Insert(const T& data)
{
    if (_root == nullptr)
    {
        _root = new Node(data);

        _root->_col = BLACK;
        return make_pair(_root, true);;
    }

    Node* parent = nullptr;
    Node* cur = _root;
    KeyOfT kot;

    while (cur)
    {
        if (kot(cur->_data) < kot(data))
        {
            parent = cur;
            cur = cur->_right;
        }
        else if (kot(cur->_data) > kot(data))
        {
            parent = cur;
            cur = cur->_left;
        }
        else
        {
            return make_pair(cur, false);;
        }
    }

    cur = new Node(data);
    Node* newnode = cur;
    //默认结点颜色为红色

    if (kot(parent->_data) < kot(data))
    {
        parent->_right = cur;
        cur->_parent = parent;
    }
    else
    {
        parent->_left = cur;
        cur->_parent = parent;
    }

    while (parent && parent->_col == RED)
    {
        Node* grandfather = parent->_parent;
        //大前提
        //parent在左
        if (parent == grandfather->_left)
        {
            Node* uncle = grandfather->_right;
            //Node* uncle = parent->_right;//错误二
            if (uncle && uncle->_col == RED)
            {
                //情景一:cur->红,parent->红,grandfather->黑,uncle存在且为红
                    //     g
                    //   p   u
                    // c
                    // 
                    //解决:p,u改为黑,g改为红,最后g为红所以,要继续向上调整
                parent->_col = uncle->_col = BLACK;
                grandfather->_col = RED;
                cur = grandfather;
                parent = cur->_parent;
            }
            else
            {
                if (cur == parent->_left)
                {
                    //情景二:cur->红,parent->红,grandfather->黑,uncle不存在/为黑
                        //     g
                        //   p   u
                        // c
                        // 
                    // 解决:对g右单旋,p改为黑,g改为红,最后g为黑所以,直接break
                    RotateR(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                }
                else
                {
                    //情景三:cur->红,parent->红,grandfather->黑,uncle不存在/为黑
                        //       g
                        //   p      u
                        //     c
                    // 解决:对p左单旋,后变为情景二。
                    RotateL(parent);
                    RotateR(grandfather);
                    cur->_col = BLACK;
                    grandfather->_col = RED;
                }
                break;
            }
        }
        else//情景大概反着来
        {
            //1  uncle
            Node* uncle = grandfather->_left;//错误一
            //Node* uncle = parent->_right;//错误一
            if (uncle && uncle->_col == RED)
            {
                parent->_col = uncle->_col = BLACK;
                grandfather->_col = RED;
                cur = grandfather;
                parent = cur->_parent;
            }

            else
            {
                if (cur == parent->_right)//2
                {
                    RotateL(grandfather);
                    parent->_col = BLACK;
                    grandfather->_col = RED;
                }
                else//3
                {
                    RotateR(parent);
                    RotateL(grandfather);
                    cur->_col = BLACK;
                    grandfather->_col = RED;
                }
                break;
            }
        }
    }
    //最后
    _root->_col = BLACK;

    return make_pair(newnode, true);;
}
void RotateL(Node* parent)
{
    Node* subR = parent->_right;
    Node* subRL = subR->_left;

    parent->_right = subRL;
    subR->_left = parent;

    Node* parentParent = parent->_parent;

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

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

        subR->_parent = parentParent;
    }
}

void RotateR(Node* parent)
{
    Node* subL = parent->_left;
    Node* subLR = subL->_right;

    parent->_left = subLR;
    if (subLR)
        subLR->_parent = parent;

    Node* parentParent = parent->_parent;

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

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

        subL->_parent = parentParent;
    }
}

iterator Find(const K& key)
{
    Node* cur = _root;
    KeyOfT kot;
    while (cur)
    {
        if (kot(cur->_data) < key)
        {
            cur = cur->_right;
        }
        else if (kot(cur->_data) > key)
        {
            cur = cur->_left;
        }
        else
        {
            return iterator(cur);
        }
    }
    return end();
}
void InOrder()
{
    _InOrder(_root);
    cout << endl;
}
void _InOrder(Node* root)
{
    if (root == nullptr)
        return;
    _InOrder(root->_left);
    cout << kof(root->_data) << " ";
    _InOrder(root->_right);
}
bool Check(Node* root, int blacknum, const int refVal)
{
    if (root == nullptr)
    {
        if (refVal != blacknum)
        {
            cout << "存在黑色节点数量不相等的路径" << endl;
            return false;
        }
        return true;
    }
    if (root->_col == RED)
    {
        if (root->_parent->_col == RED)
        {
            cout << "有连续的红色节点" << endl;
            return false;
        }
    }
    if (root->_col == BLACK)
    {
        ++blacknum;
    }
    return Check(root->_left, blacknum, refVal)
        && Check(root->_right, blacknum, refVal);

}
bool IsBalance()
{
    //1:是否存在 红-红 
   //每条路径黑色结点是否相同个数
   //最长的不超过最短的二倍
   //根,叶子为黑
    if (_root == nullptr)
        return true;
    if (_root->_col == RED)
        return false;
    int refVal = 0;
    Node* cur = _root;
    while (cur)
    {
        if (cur->_col == BLACK)
        {
            ++refVal;
        }
        cur = cur->_left;
    }
    int blacknum = 0;
    return Check(_root, blacknum, refVal);
}

private:
Node* _root = nullptr;
};
set的代码

pragma once

include"RBTree.h"

namespace myset
{
template
class set
{
public:
//仿函数
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
typedef typename RBTree::const_iterator iterator;
typedef typename RBTree::const_iterator const_iterator;
iterator begin() const
{
return _t.begin();
}
iterator end() const
{
return _t.end();
}
pair insert(const K& key)
{
return _t.Insert(key);
}
bool IsBalance()
{
return _t.IsBalance();
}
private:
RBTree _t;
};
}
map的代码

pragma once

include"RBTree.h"

namespace mymap
{
template
class map
{
public:
//仿函数
struct MapKeyOfT
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
// 对类模板取内嵌类型,加typename告诉编译器这里是类型
typedef typename RBTree, MapKeyOfT>::iterator iterator;
typedef typename RBTree, MapKeyOfT>::const_iterator const_iterator;
iterator begin() const
{
return _t.begin();
}
iterator end() const
{
return _t.end();
}
pair insert(const pair& kv)
{
return _t.Insert(kv);
}
V& operator
{
pair < iterator, bool> ret = insert(make_pair(key, V()));//默认构造为0
//V():在这里,V() 是一个临时创建的 V 类型的对象。
// 它使用 V 类型的默认构造函数创建一个默认的值对象。
// 这样做的目的是为了确保即使映射中没有该键,
// 也能够返回一个默认构造的值的引用,以便在插入新键值对时,
// 通过返回引用,可以直接为新键关联一个默认构造的值。
return ret.first->second;
}
bool IsBalance()
{
return _t.IsBalance();
}
private:
RBTree, MapKeyOfT> _t;
};
}

目录
相关文章
|
2月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
234 1
|
5月前
|
存储 缓存 JavaScript
Set和Map有什么区别?
Set和Map有什么区别?
465 1
|
2月前
|
存储 算法 容器
set_map的实现+set/map加持秒杀高频算法题锻炼算法思维
`set`基于红黑树实现,支持有序存储、自动去重,增删查效率为O(logN)。通过仿函数可自定义排序规则,配合空间配置器灵活管理内存。不支持修改元素值,迭代器失效需注意。`multiset`允许重复元素。常用于去重、排序及查找场景。
|
6月前
|
存储 JavaScript 前端开发
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
343 121
|
6月前
|
安全 Java 数据库连接
让我们讲解一下 Map 集合遍历的方式
我是小假 期待与你的下一次相遇 ~
272 43
使用 entrySet 遍历 Map 类集合 KV
使用 entrySet 遍历 Map 类集合 KV
|
存储 前端开发 API
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
该文章详细介绍了ES6中Set和Map数据结构的特性和使用方法,并探讨了它们在前端开发中的具体应用,包括如何利用这些数据结构来解决常见的编程问题。
ES6的Set和Map你都知道吗?一文了解集合和字典在前端中的应用
|
存储 安全 Java
java集合框架复习----(4)Map、List、set
这篇文章是Java集合框架的复习总结,重点介绍了Map集合的特点和HashMap的使用,以及Collections工具类的使用示例,同时回顾了List、Set和Map集合的概念和特点,以及Collection工具类的作用。
java集合框架复习----(4)Map、List、set
|
Go 定位技术 索引
Go 语言Map(集合) | 19
Go 语言Map(集合) | 19

热门文章

最新文章