目录
一、基础铺垫
二、基本结构分析
1. 节点结构分析
2. 模板参数中仿函数分析
三、正向迭代器
四、封装完成的红黑树
五、map的模拟实现
六、set的模拟实现
一、基础铺垫
在前面的博客中我们了解了map和set的基本使用,以及对二叉搜索树、AVL树和红黑树的概念和简单实现有了一定的了解后,对于map和set来说,他们的底层实现都是基于红黑树的。我们知道set是key的模型、map是key/value的模型,那么一棵红黑树是如何实现出map和set的呢?
二、基本结构分析
1. 节点结构分析
以上是截取的部分源码结构,我们可以看到set的模板参数是Key,map的模板参数是Key和T;set将Key这个模板参数typedef成了key_type和value_type,map将Key这个模板参数typedef成了key_type、将T这个模板参数typedef成了data_type;
他们同时调用红黑树时,都是用的value_type,对应set的value_type是Key,对应map的value_type是pair<const key,T>;这意味着红黑树只看传过来的value_type是什么类型的,当上层容器是set的时候,结点当中存储的是键值Key;当上层容器是map的时候,结点当中存储的就是<Key, Value>键值对。
结点结构:
enum Colour
{
RED,
BLACK
};
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;//存储的数据类型:如果是set,T对应的就是K;如果是map,T对应的就是pair
Colour _col;
RBTreeNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
, _data(data)
{}
};
红黑树基本结构:
template<class k, class T>
class RBTree
{
typedef RBTreeNode<T> Node;
private:
Node* _root;
};
map的基本结构:
namespace mlg
{
template<class k, class v>
class map
{
private:
RBTree<k, pair<k, v>> _t;
};
}
set的基本结构:
namespace mlg
{
template<class k>
class set
{
private:
RBTree<k, k> _t;
};
}
2. 模板参数中仿函数分析
因为红黑树中存储的是T类型,有可能是Key,也有可能是<Key, Value>键值对;那么当我们需要进行结点的键值比较时,应该如何获取结点的键值呢?
当上层容器是set的时候T就是键值Key,直接用T进行比较即可,但当上层容器是map的时候就不行了,此时我们需要从<Key, Value>键值对当中取出键值Key后,再用Key值进行比较。
因此,上层容器map需要向底层红黑树提供一个仿函数,用于获取T当中的键值Key,这样一来,当底层红黑树当中需要比较两个结点的键值时,就可以通过这个仿函数来获取T当中的键值了。
map的仿函数:
namespace mlg
{
template<class k, class v>
class map
{
public:
struct MapKeyOfT
{
const k& operator()(const pair<k, v>& kv)
{
return kv.first;
}
};
private:
RBTree<k, pair<k, v>, MapKeyOfT> _t;
};
}
set的仿函数:
namespace mlg
{
template<class k>
class set
{
public:
struct SetKeyOfT
{
const k& operator()(const k& k)
{
return k;
}
};
private:
RBTree<k, k, SetKeyOfT> _t;
};
}
三、正向迭代器
红黑树的正向迭代器实际上就是对结点指针进行了封装,因此在正向迭代器当中实际上就只有一个成员变量,那就是正向迭代器所封装结点的指针。
template<class T, class Ref, class Ptr>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;//结点的类型
typedef RBTreeIterator<T, Ref, Ptr> Self;//正向迭代器的类型
Node* _node;//正向迭代器所封装结点的指针
RBTreeIterator(Node* node)//根据所给结点指针构造一个正向迭代器
:_node(node)
{}
Ref operator*()
{
return _node->_data;//返回结点数据的引用
}
Ptr operator->()
{
return &_node->_data;//返回结点数据的指针
}
//前置++
/*
如果当前结点的右子树不为空,则++操作后应该找到其右子树当中的最左结点。
如果当前结点的右子树为空,则++操作后应该在该结点的祖先结点中,找到孩子不在父亲右的祖先。
*/
Self& operator++()
{
if (_node->_right)//结点的右子树不为空
{
Node* min = _node->_right;
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else //结点的右子树为空
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
//前置--
/*
如果当前结点的左子树不为空,则--操作后应该找到其左子树当中的最右结点。
如果当前结点的左子树为空,则--操作后应该在该结点的祖先结点中,找到孩子不在父亲左的祖先。
*/
Self& operator--()
{
if (_node->_left)
{
Node* max = _node->_left;
while (max->_right)
{
max = max->_right;
}
_node = max;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
//判断两个正向迭代器是否不同
bool operator!=(const Self& s)const
{
return _node != s._node;
}
//判断两个正向迭代器是否相同
bool operator==(const Self& s)const
{
return _node == s._node;
}
};
四、封装完成的红黑树
#pragma once
#include <iostream>
#include <algorithm>
using namespace std;
enum Colour
{
RED,
BLACK
};
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
Colour _col;
RBTreeNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
, _data(data)
{}
};
template<class T, class Ref, class Ptr>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, Ref, Ptr> Self;
Node* _node;
RBTreeIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
//前置++
Self& operator++()
{
if (_node->_right)
{
Node* min = _node->_right;
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
//前置--
Self& operator--()
{
if (_node->_left)
{
Node* max = _node->_left;
while (max->_right)
{
max = max->_right;
}
_node = max;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
bool operator!=(const Self& s)const
{
return _node != s._node;
}
bool operator==(const Self& s)const
{
return _node == s._node;
}
};
//set RBTree<k, k>
//map RBTree<k, pair<k, v>>
template<class k, class T, class keyofT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef RBTreeIterator<T, T&, T*> iterator;
typedef RBTreeIterator<T, const T&, const T*> const_iterator;
iterator begin()
{
Node* min = _root;
while (min && min->_left)
{
min = min->_left;
}
return iterator(min);
}
iterator end()
{
return iterator(nullptr);
}
RBTree()
:_root(nullptr)
{}
RBTree(const RBTree<k, T, keyofT>& t)
{
_root = Copy(t._root);
}
Node* Copy(Node* root)
{
if (root == nullptr)
{
return nullptr;
}
Node* newRoot = new Node(root->_data);
newRoot->_col = root->_col;
newRoot->_left = Copy(root->_left);
newRoot->_right = Copy(root->_right);
if (newRoot->_left)
{
newRoot->_left->_parent = newRoot;
}
if (newRoot->_right)
{
newRoot->_right->_parent = newRoot;
}
return newRoot;
}
RBTree<k, T, keyofT>& operator=(RBTree<k, T, keyofT> t)
{
swap(_root, t._root);
return *this;
}
~RBTree()
{
Destroy(_root);
_root = nullptr;
}
void Destroy(Node* root)
{
if (root == nullptr)
{
return;
}
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
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();
}
pair<iterator, bool> Insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
keyofT kot;
Node* parent = nullptr;
Node* cur = _root;
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(iterator(cur), false);
}
}
cur = new Node(data);
Node* newnode = cur;
cur->_col = RED; // 新增节点
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;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
// 1、uncle存在且为红
if (uncle && uncle->_col == RED)
{
// 变色+继续向上处理
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else // 2 + 3、uncle不存在/ 存在且为黑
{
if (cur == parent->_left)
{
// 单旋
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// 双旋
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else // parent == grandfather->_right
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
// 变色+继续向上处理
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else // 2 + 3、uncle不存在/ 存在且为黑
{
if (cur == parent->_right)
{
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return make_pair(iterator(newnode), true);
}
//左单选
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
{
subRL->_parent = parent;
}
Node* parentParent = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (parent == _root)//这里表明原来是根
{
_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 (parent == _root)//这里表明原来是根
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (parentParent->_left == parent)
{
parentParent->_left = subL;
}
else
{
parentParent->_right = subL;
}
subL->_parent = parentParent;
}
}
void InOrder()
{
_InOrder(_root);
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;
_InOrder(root->_right);
}
private:
Node* _root;
};
五、map的模拟实现
#include "RBTree.h"
namespace mlg
{
template<class k, class v>
class map
{
public:
struct MapKeyOfT
{
const k& operator()(const pair<k, v>& kv)
{
return kv.first;
}
};
typedef typename RBTree<k, pair<k, v>, MapKeyOfT>::iterator iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
pair<iterator, bool> insert(const pair<k, v>& kv)
{
return _t.Insert(kv);
}
iterator find(const k& key)
{
return _t.Find(key);
}
v& operator[](const k& key)
{
auto ret = _t.Insert(make_pair(key, v()));
return ret.first->second;
}
private:
RBTree<k, pair<k, v>, MapKeyOfT> _t;
};
}
六、set的模拟实现
#include "RBTree.h"
namespace mlg
{
template<class k>
class set
{
public:
struct SetKeyOfT
{
const k& operator()(const k& k)
{
return k;
}
};
typedef typename RBTree<k, k, SetKeyOfT>::iterator iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
pair<iterator, bool> insert(const k& key)
{
return _t.Insert(key);
}
iterator find(const k& key)
{
return _t.Find(key);
}
private:
RBTree<k, k, SetKeyOfT> _t;
};
}