map、set 是 C++ 中的关联式容器,由于 map 和set所开放的各种操作接口,RB-tree 也都提供了,所以几乎所有的 map 和set的操作行为,都只是转调 红黑树 的操作行为。
关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是
map、set 一个很明显的区别就是,set 存储值,map存储键值对。
set 的结构如下,只需要传入一个模板参数 K ,也就是其实际存储的值的数据类型。复用红黑树的时候,第二个参数就是 K 类型。
#pragma once
#include"rb_tree.h"
namespace SetSimulate
{
template<class K>
class set
{
struct KeyOfT
{
const K& operator()(const K& k)
{
return k;
}
};
public:
typedef typename RBTree<K, K, KeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, KeyOfT>::const_iterator const_iterator;
private:
RBTree<K, K, KeyOfT> _t;
};
}
而 Map 就不一样了,要传入两个参数,第一个是 K(键值),第二个是 V (映射值)。实际存储的数据类型是 pair
#pragma once
#include"rb_tree.h"
namespace MapSimulate
{
template<class K, class V>
class map
{
struct MapOfKey
{
const K& operator()(const pair<const K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree<K, pair<const K,V>, MapOfKey>::iterator iterator;
typedef typename RBTree<K, pair<const K,V>, MapOfKey>::const_iterator const_iterator;
typedef typename RBTree<K, pair<const K, V>, MapOfKey>::reverse_iterator reverse_iterator;
typedef typename RBTree<K, pair<const K, V>, MapOfKey>::const_reverse_iterator const_reverse_iterator;
private:
RBTree<K, pair<const K, V>, MapOfKey> _t;
};
}
关于 map、set 底层红黑树的第三个模板参数,分析上面的两段代码,实际上是取存储数据的 K 值。即,在 map 里面,由于存储的数据类型是 pair
至于为什么要这样,这是因为,map、set 是对红黑树的封装,如果仅仅实现 set ,可以不用给红黑树传入第三个模板参数,因为 set 里面存储 K 类型的数据,而红黑树插入、查找、删除等等操作里面,数据之间进行比较,本就是比较的 K 类型的数据,所以是一致的。
但是,map 存储的是 pair
当然,上面两端说起来比较抽象,接下来介绍一下 Find 封装,就不难理解了。
如下是红黑树底层实现 find 的代码。可以看到它在进行数据之间的比较时,是依靠 KeyOfT 实例化出的对象 kt ,取 kt(cur->_data) 。
很显然,当容器无论为 set 还是 map, 红黑树中 find() 函数都依靠 K 类型的 val 来查找。可是, 红黑树的节点中, _data 存储的数据类型却不一样,map 中存储的是 pair
所以,这里就依靠红黑树的第三个模板参数 KeyOfT 实例化的对象 kt,其重载的 () 来取到 map、set 的 _data 里面的 K 值。这样就统一了。
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
Colour _col;
RBTreeNode(const T& val)
: _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(val)
, _col(RED)
{}
};
template<class K, class T, class KeyOfT>
class RBTree
{
typedef struct RBTreeNode<T> Node;
public:
Node* find(const K& val)
{
KeyOfT kt;
Node* cur = _root;
while (cur)
{
if (val > kt(cur->_data))
{
cur = cur->_right;
}
else if (val < kt(cur->_data))
{
cur = cur->_left;
}
else
return cur;
}
return nullptr;
}
private:
Node* _root;
};
如下,无论是 map 还是 set,都是直接调用红黑树的 find() ,然后封装成迭代器返回。
iterator Find(const K& key)
{
Node* cur = _t.find(key);
return iterator(cur);
}
如下,是迭代器的大体框架,主要依靠红黑树的节点指针来实现。
重载 * 、->、!= 都比较简单,和 list 封装的迭代器类似。但是 ,重载 ++ 和 – 就需要一些独特的思路了!
template<class T,class Ref,class Ptr>
struct _RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef _RBTreeIterator<T, Ref, Ptr> self;
_RBTreeIterator(Node* node)
:_node(node)
{}
// begin() 、 end() 处可见其效果
_RBTreeIterator(const _RBTreeIterator<T, T&, T*> &it)
:_node(it._node)
{}
Ref operator*()
{
return _node->_data;
}
bool operator!=(const self& s)
{
return this->_node != s._node;
}
Ptr operator->()
{
return &_node->_data;
}
self& operator++()
{
// 实现
return *this;
}
self& operator--()
{
// 实现
return *this;
}
Node* _node;
};
operator++()
对红黑树的遍历,和搜索二叉树是一样的,中序遍历。
例如,现在某棵红黑树存储了1到10 的数据,使用迭代器遍历的结果必然是 1、2、3、4、5、6、7、8、9、10。
假设现在将存储 5 这个数据的节点,封装成迭代器 it。进行 ++it 操作之后,无疑 it 内部的节点指针,指向的是数据为 6 的节点。再 ++it,it 内部的结点指针就指向数据为 7 的节点。
很明显,++ 操作,只需要考虑右边部分的结果(上面依次++it,实际上节点指针依次指向 6、7、8、9、10 ),不需要考虑 左边的部分(即 1-5 )。
这样就很清晰了,对于一个中序遍历的结果,对于某一个节点 X 的右边部分,分为两种情况:有数据是 X 的子节点(可能是部分,可能是全部);没有数据是 X 的子节点。例如上面 5 这个结果,其右边部分6到10 里面,可能有数据是5的子节点,也可能没有。
根据这两种情况来写代码。
对于第一种情况——右边部分存在 X 的子节点。这就很容易了,由于是中序遍历,当前节点遍历完之后,就需要遍历其右子树。所以 ++ 操作,只要找到其右子树的最小节点即可。
对于第二种情况,X 不存在右子树,那么必然是要往上找。如下图,假设一开始是图中左边的状态, 现在有 cur 、p 两个节点指针,而 cur 没有右子树,向上寻找, cur 在 p 的右边,这说明 p 已经遍历过了。
再继续往上找,到了下图右边的状态,此时 cur 在 p 的左边,根据中序遍历规则,下一个要遍历的节点就是 此时的 p。
self& operator++()
{
// 右子树存在,先去右子树的第一个
if (_node->_right)
{
Node* subleft=_node->_right;
while (subleft->_left)
{
subleft = subleft->_left;
}
_node = subleft;
}
else // 右子树不存在,向上找
{
Node* cur = _node;
Node* parent = _node->_parent;
while (parent && parent->_right == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
operator–()
而 – 就是和 ++ 反过来了,遍历顺序是:右子树、根、左子树。所以,拿到某个节点 X,要先去看左子树是否存在,不存在则往上找。
self& operator--()
{
if (_node->_left)
{
Node* subright = _node->_left;
while (subright->_right)
{
subright = subright->_right;
}
_node = subright;
}
else // 当前节点没有左子树,直接向上找,直到 parent 的左子节点是 cur
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && parent->_left == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
反向迭代器主要是对正向迭代器的封装。
template<class T, class Ref, class Ptr>
struct _RBTreeReverseIterator
{
typedef RBTreeNode<T> Node;
typedef _RBTreeReverseIterator<T, Ref, Ptr> self;
_RBTreeReverseIterator(Node* node)
{
_it._node = node;
}
_RBTreeReverseIterator(const _RBTreeIterator<T, T&, T*>& it)
{
_it._node = it._node;
}
_RBTreeReverseIterator(const _RBTreeReverseIterator<T, T&, T*>& it)
{
_it._node = it._it._node;
}
self& operator++()
{
--_it;
return *this;
}
self& operator--()
{
++_it;
return *this;
}
bool operator!=(const self& s)
{
return _it._node != s._it._node;
}
Ptr operator->()
{
return &_it._node->_data;
}
Ref operator*()
{
return _it._node->_data;
}
struct _RBTreeIterator<T,Ref,Ptr> _it=nullptr;
};
在红黑树中实现了 迭代器,接下来就是封装到 map、set 里面。与此同时,还需要红黑树中提供 begin() 、end() 、rbegin() 、rend() 方法。
如下,是在红黑树中实现这些方法,返回的结果是迭代器。
template<class K, class T, class KeyOfT>
class RBTree
{
typedef struct RBTreeNode<T> Node;
public:
typedef _RBTreeIterator<T, T&, T*> iterator;
typedef _RBTreeIterator<T, const T&, const T*> const_iterator;
typedef _RBTreeReverseIterator<T, T&, T*> reverse_iterator;
typedef _RBTreeReverseIterator<T, const T&, const T*> const_reverse_iterator;
public:
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);
}
reverse_iterator rbegin()
{
Node* cur = _root;
while (cur && cur->_right)
{
cur = cur->_right;
}
return reverse_iterator(cur);
}
reverse_iterator rend()
{
return reverse_iterator(nullptr);
}
const_reverse_iterator rbegin() const
{
Node* cur = _root;
while (cur && cur->_right)
{
cur = cur->_right;
}
return const_reverse_iterator(cur);
}
const_reverse_iterator rend() const
{
return const_reverse_iterator(nullptr);
}
private:
Node* _root;
};
如下是在 set 里面实现 begin() 、end() ,完全是对 红黑树方法的复用。
值得注意的是, typedef typename RBTree
#pragma once
#include"rb_tree.h"
namespace SetSimulate
{
template<class K>
class set
{
struct KeyOfT
{
const K& operator()(const K& k)
{
return k;
}
};
public:
typedef typename RBTreeNode<K> Node;
typedef typename RBTree<K, K, KeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, KeyOfT>::const_iterator const_iterator;
typedef typename RBTree<K, K, KeyOfT>::const_reverse_iterator reverse_iterator;
typedef typename RBTree<K, K, KeyOfT>::const_reverse_iterator const_reverse_iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
const_iterator begin()const
{
return _t.begin();
}
const_iterator end()const
{
return _t.end();
}
reverse_iterator rbegin()
{
return _t.rbegin();
}
reverse_iterator rend()
{
return _t.rend();
}
const_reverse_iterator rbegin()const
{
return _t.rbegin();
}
const_reverse_iterator rend()const
{
return _t.rend();
}
iterator Find(const K& key)
{
Node* cur = _t.find(key);
return iterator(cur);
}
private:
RBTree<K, K, KeyOfT> _t;
};
}
首先,map 的 [ ] 是兼具插入和查找功能的。map 里面存储的是 pair
要完成上面描述的功能,就必须要让 [ ] 的返回值是 V& (V的引用),这样才可以修改 V 类型的数据。 可以通过迭代器来实现!!
如下是 map 里面实现 operator[ ] 的代码,_t 是红黑树实例化出来的对象,其 Insert() 返回值是 pair
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
return ret.first->second;
}
那么就可以对红黑树底层的 Insert() 进行修改,只需要修改函数的返回值类型,以及 return 的时候,构造一个 make_pair
#pragma once
#include
#include
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& val)
: _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(val)
, _col(RED)
{}
};
template<class T,class Ref,class Ptr>
struct _RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef _RBTreeIterator<T, Ref, Ptr> self;
_RBTreeIterator(Node* node)
:_node(node)
{}
_RBTreeIterator(const _RBTreeIterator<T, T&, T*> &it)
:_node(it._node)
{}
Ref operator*()
{
return _node->_data;
}
bool operator!=(const self& s)
{
return this->_node != s._node;
}
Ptr operator->()
{
return &_node->_data;
}
self& operator++()
{
// 右子树存在,先去右子树的第一个
if (_node->_right)
{
Node* subleft=_node->_right;
while (subleft->_left)
{
subleft = subleft->_left;
}
_node = subleft;
}
else // 右子树不存在,向上找
{
Node* cur = _node;
Node* parent = _node->_parent;
while (parent && parent->_right == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
self& operator--()
{
if (_node->_left)
{
Node* subright = _node->_left;
while (subright->_right)
{
subright = subright->_right;
}
_node = subright;
}
else // 当前节点没有左子树,直接向上找,直到 parent 的左子节点是 cur
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && parent->_left == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Node* _node;
};
template<class T, class Ref, class Ptr>
struct _RBTreeReverseIterator
{
typedef RBTreeNode<T> Node;
typedef _RBTreeReverseIterator<T, Ref, Ptr> self;
_RBTreeReverseIterator(Node* node)
{
_it._node = node;
}
_RBTreeReverseIterator(const _RBTreeIterator<T, T&, T*>& it)
{
_it._node = it._node;
}
_RBTreeReverseIterator(const _RBTreeReverseIterator<T, T&, T*>& it)
{
_it._node = it._it._node;
}
self& operator++()
{
--_it;
return *this;
}
self& operator--()
{
++_it;
return *this;
}
bool operator!=(const self& s)
{
return _it._node != s._it._node;
}
Ptr operator->()
{
return &_it._node->_data;
}
Ref operator*()
{
return _it._node->_data;
}
struct _RBTreeIterator<T,Ref,Ptr> _it=nullptr;
};
template<class K, class T, class KeyOfT>
class RBTree
{
typedef struct RBTreeNode<T> Node;
public:
typedef _RBTreeIterator<T, T&, T*> iterator;
typedef _RBTreeIterator<T, const T&, const T*> const_iterator;
typedef _RBTreeReverseIterator<T, T&, T*> reverse_iterator;
typedef _RBTreeReverseIterator<T, const T&, const T*> const_reverse_iterator;
public:
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);
}
reverse_iterator rbegin()
{
Node* cur = _root;
while (cur && cur->_right)
{
cur = cur->_right;
}
return reverse_iterator(cur);
}
reverse_iterator rend()
{
return reverse_iterator(nullptr);
}
const_reverse_iterator rbegin() const
{
Node* cur = _root;
while (cur && cur->_right)
{
cur = cur->_right;
}
return const_reverse_iterator(cur);
}
const_reverse_iterator rend() const
{
return const_reverse_iterator(nullptr);
}
~RBTree()
{
Delete(_root);
_root = nullptr;
}
Node* find(const K& val)
{
KeyOfT kt;
Node* cur = _root;
while (cur)
{
if (val > kt(cur->_data))
{
cur = cur->_right;
}
else if (val < kt(cur->_data))
{
cur = cur->_left;
}
else
return cur;
}
return nullptr;
}
pair<iterator,bool> Insert(const T& val)
{
if (_root == nullptr)
{
_root = new Node(val);
_root->_col = BLACK;
return make_pair(iterator(_root),true);
}
KeyOfT kt;
Node* parent = nullptr;
Node* cur = _root;
while (cur) // 找到要插入的位置
{
if (kt(cur->_data) > kt(val))
{
parent = cur;
cur = cur->_left;
}
else if (kt(cur->_data) < kt(val))
{
parent = cur;
cur = cur->_right;
}
else
return make_pair(iterator(cur), false);
}
// 插入
cur = new Node(val);
Node* newnode = cur;
if (kt(parent->_data) < kt(val))
{
parent->_right = cur;
}
else if (kt(parent->_data) > kt(val))
{
parent->_left = cur;
}
cur->_parent = parent;
// 调整颜色
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED) // uncle 为红色
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
// 继续调整
cur = grandfather;
parent = cur->_parent;
}
else // uncle不存在 or 存在且为黑
{
if (cur == parent->_left)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
//cur->_col = RED;
}
else if (cur == parent->_right)
{
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
parent->_col = RED;
}
break;
}
}
else // if (parent == grandfather->_right)
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED) // uncle 为红色
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
// 继续调整
cur = grandfather;
parent = cur->_parent;
}
else // uncle不存在 or 存在且为黑
{
if (cur == parent->_right)
{
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
//cur->_col = RED;
}
else // cur == parent->_left
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
parent->_col = RED;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return make_pair(iterator(newnode), true);
}
int Height()
{
return _Height(_root);
}
bool isBalance()
{
if (_root->_col == RED)
{
cout << "根节点的颜色是红色" << endl;
return false;
}
int benchmark = 0;
Node* tmp = _root;
while (tmp)
{
if (tmp->_col == BLACK)
benchmark++;
tmp = tmp->_left;
}
return _isBalance(_root, 0, benchmark);
}
void Inorder()
{
_Inorder(_root);
}
private:
void _Inorder(Node* root)
{
if (root == nullptr)
return;
_Inorder(root->_left);
cout << root->_kv.first << " ";
_Inorder(root->_right);
}
bool _isBalance(Node* root, int blackNum, int benchmark)
{
if (root == nullptr)
{
if (blackNum == benchmark)
return true;
else
{
cout << "某条链路黑色节点数目错误!" << endl;
return false;
}
}
if (root->_col == BLACK)
++blackNum;
else
{
if (root->_parent && root->_parent->_col == RED)
{
cout << "存在两个连续的红色节点" << endl;
return false;
}
}
return _isBalance(root->_left, blackNum, benchmark)
&& _isBalance(root->_right, blackNum, benchmark);
}
int _Height(Node* root)
{
if (root == nullptr) return 0;
int leftH = _Height(root->_left);
int rightH = _Height(root->_right);
return leftH > rightH ? leftH + 1 : rightH + 1;
}
void Delete(Node* root)
{
if (root == nullptr)
return;
Delete(root->_left);
Delete(root->_right);
free(root);
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
Node* pparent = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
if (pparent == nullptr)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if (parent == pparent->_left)
{
pparent->_left = subR;
}
else
{
pparent->_right = subR;
}
subR->_parent = pparent;
}
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* pparent = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
if (pparent == nullptr)
{
subL->_parent = nullptr;
_root = subL;
}
else
{
if (parent == pparent->_left)
{
pparent->_left = subL;
}
else
{
pparent->_right = subL;
}
subL->_parent = pparent;
}
}
private:
Node* _root;
};
#pragma once
#include"rb_tree.h"
namespace SetSimulate
{
template<class K>
class set
{
struct KeyOfT
{
const K& operator()(const K& k)
{
return k;
}
};
public:
typedef typename RBTreeNode<K> Node;
typedef typename RBTree<K, K, KeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, KeyOfT>::const_iterator const_iterator;
typedef typename RBTree<K, K, KeyOfT>::const_reverse_iterator reverse_iterator;
typedef typename RBTree<K, K, KeyOfT>::const_reverse_iterator const_reverse_iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
const_iterator begin()const
{
return _t.begin();
}
const_iterator end()const
{
return _t.end();
}
reverse_iterator rbegin()
{
return _t.rbegin();
}
reverse_iterator rend()
{
return _t.rend();
}
const_reverse_iterator rbegin()const
{
return _t.rbegin();
}
const_reverse_iterator rend()const
{
return _t.rend();
}
pair<iterator,bool> insert(const K& k)
{
return _t.Insert(k);
}
iterator Find(const K& key)
{
Node* cur = _t.find(key);
return iterator(cur);
}
private:
RBTree<K, K, KeyOfT> _t;
};
}
#pragma once
#include"rb_tree.h"
namespace MapSimulate
{
template<class K, class V>
class map
{
struct MapOfKey
{
const K& operator()(const pair<const K, V>& kv)
{
return kv.first;
}
};
public:
typedef typename RBTreeNode<pair<const K, V>> Node;
typedef typename RBTree<K, pair<const K,V>, MapOfKey>::iterator iterator;
typedef typename RBTree<K, pair<const K,V>, MapOfKey>::const_iterator const_iterator;
typedef typename RBTree<K, pair<const K, V>, MapOfKey>::reverse_iterator reverse_iterator;
typedef typename RBTree<K, pair<const K, V>, MapOfKey>::const_reverse_iterator const_reverse_iterator;
pair<iterator,bool> insert(const pair<const K, V>& kv)
{
return _t.Insert(kv);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
return ret.first->second;
}
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
const_iterator begin()const
{
return _t.begin();
}
const_iterator end()const
{
return _t.end();
}
reverse_iterator rbegin()
{
return _t.rbegin();
}
reverse_iterator rend()
{
return _t.rend();
}
const_reverse_iterator rbegin()const
{
return _t.rbegin();
}
const_reverse_iterator rend()const
{
return _t.rend();
}
iterator Find(const K& key)
{
Node* cur = _t.find(key);
return iterator(cur);
}
private:
RBTree<K, pair<const K, V>, MapOfKey> _t;
};
}