用一棵红黑树同时封装出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;
};
}

相关文章
|
13天前
|
存储 JavaScript 前端开发
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
33 0
|
13天前
|
存储 C++ 容器
unordered_set、unordered_multiset、unordered_map、unordered_multimap的介绍及使用
unordered_set是不按特定顺序存储键值的关联式容器,其允许通过键值快速的索引到对应的元素。在unordered_set中,元素的值同时也是唯一地标识它的key。在内部,unordered_set中的元素没有按照任何特定的顺序排序,为了能在常数范围内找到指定的key,unordered_set将相同哈希值的键值放在相同的桶中。unordered_set容器通过key访问单个元素要比set快,但它通常在遍历元素子集的范围迭代方面效率较低。它的迭代器至少是前向迭代器。前向迭代器的特性。
|
13天前
|
存储 编译器 容器
set、map、multiset、multimap的介绍及使用以及区别,注意事项
set是按照一定次序存储元素的容器,使用set的迭代器遍历set中的元素,可以得到有序序列。set当中存储元素的value都是唯一的,不可以重复,因此可以使用set进行去重。set默认是升序的,但是其内部默认不是按照大于比较,而是按照小于比较。set中的元素不能被修改,因为set在底层是用二叉搜索树来实现的,若是对二叉搜索树当中某个结点的值进行了修改,那么这棵树将不再是二叉搜索树。
|
3月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
97 2
|
4月前
|
编译器 容器
哈希表模拟封装unordered_map和unordered_set
哈希表模拟封装unordered_map和unordered_set
|
4月前
|
编译器 测试技术 计算机视觉
红黑树模拟封装map和set
红黑树模拟封装map和set
|
6月前
|
算法
你对Collection中Set、List、Map理解?
你对Collection中Set、List、Map理解?
128 18
你对Collection中Set、List、Map理解?
|
6月前
|
存储 缓存 安全
只会“有序无序”?面试官嫌弃的List、Set、Map回答!
小米,一位热衷于技术分享的程序员,通过与朋友小林的对话,详细解析了Java面试中常见的List、Set、Map三者之间的区别,不仅涵盖了它们的基本特性,还深入探讨了各自的实现原理及应用场景,帮助面试者更好地准备相关问题。
125 20
|
7月前
|
存储 C++ 容器
【C++】map、set基本用法
本文介绍了C++ STL中的`map`和`set`两种关联容器。`map`用于存储键值对,每个键唯一;而`set`存储唯一元素,不包含值。两者均基于红黑树实现,支持高效的查找、插入和删除操作。文中详细列举了它们的构造方法、迭代器、容量检查、元素修改等常用接口,并简要对比了`map`与`set`的主要差异。此外,还介绍了允许重复元素的`multiset`和`multimap`。
154 3
【C++】map、set基本用法
|
7月前
|
存储 算法 C++
【C++】unordered_map(set)
C++中的`unordered`容器(如`std::unordered_set`、`std::unordered_map`)基于哈希表实现,提供高效的查找、插入和删除操作。哈希表通过哈希函数将元素映射到特定的“桶”中,每个桶可存储一个或多个元素,以处理哈希冲突。主要组成部分包括哈希表、哈希函数、冲突处理机制、负载因子和再散列,以及迭代器。哈希函数用于计算元素的哈希值,冲突通过开链法解决,负载因子控制哈希表的扩展。迭代器支持遍历容器中的元素。`unordered_map`和`unordered_set`的插入、查找和删除操作在理想情况下时间复杂度为O(1),但在冲突较多时可能退化为O(n)。
102 5
下一篇
oss创建bucket
OSZAR »