在STL中,map和set底层都是用红黑树实现的,在前面一篇博客模拟实现了红黑树后,这篇博客要对map和set进行封装,以了解及熟悉其底层实现。
set只存储key值,将key值作为关键码,作为被搜索的对象,属于k模型;而map存储的是一个键值对,每一个key值对应一个value值,但底层的红黑树是k模型还是kv模型?如果是k模型,模板参数只有一个k,如果是kv模型,模板参数有两个,一个k一个v。参考了STL源码,我发现红黑树将k模型和kv模型抽象出来,即只使用一个模板参数T,set封装时传k,map封装时将k和v打包成pair传给T。
set将key作为第二个参数传给re_tree
map将用key和T打包成的键值对作为第二个参数传给rb_tree
rb_tree的第二个参数作为node的参数
总之,re_tree中存储的数据类型为value。(第一个参数有什么用?第一个参数是key的类型,第一个参数常用在搜索函数,需要用key值搜索,所以第一个参数要作为函数的参数类型存在)
template <class K, class V>
struct RBTreeNode
{
pair<K, V> _kv;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Colour _col;
RBTreeNode(pair<K, V> kv)
:_kv(kv)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{}
};
所以对之前实现的代码进行改造
template <class T>
struct RBTreeNode
{
T _data;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Colour _col;
RBTreeNode(T data)
:_data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{}
};
节点中存储的数据类型统一成T,那么在比较时有两种情况,一种T是key可以直接进行比较,另一种T是pair,比较时要用pair的first数据进行比较,但看文档之后,pair确实有重载比较,但比较的规则不是我们想要的:没有用first来判断pair的大小
但又不能再重载一次(函数名相同,参数相同,再重载的话跟库中重载的冲突),STL是怎么解决这个问题的?STL使用了仿函数,分别在map和set中定义仿函数,将仿函数作为第三个传给re_tree,通过这个仿函数能取出T中我们需要比较的对象,对于set比较的对象就是key,对于map比较的对象就是pair的first
(KeyOfValue在STL中的一个使用,用KeyOfValue构造匿名对象,由于KeyOfValue重载了(),将v作为参数就能得到要进行比较的对象)
#pragma once
#include
using namespace std;
#include
#include
enum Colour
{
RED,
BLACK
};
template <class T>
struct RBTreeNode
{
T _data;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Colour _col;
RBTreeNode(T data)
:_data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{}
};
template <class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
bool Insert(const T& data);
void Inorder() { _Inorder(_root); }
private:
void RotateL(Node* parent);
void RotateR(Node* parent);
void _Inorder(Node* root);
private:
Node* _root = nullptr;
};
template <class K, class T, class KeyOfT>
bool RBTree<K, T, KeyOfT>::Insert(const T& data)
{
KeyOfT kot;
// 以搜索二叉树的规则插入
if (_root == nullptr)
{
_root = new Node(data);
// 根节点为黑色
_root->_col = BLACK;
return true;
}
Node* cur = _root;
Node* parent = nullptr;
// 找合适的插入位置
while (cur)
{
if (kot(data) < kot(cur->_data))
{
parent = cur;
cur = cur->_left;
}
else if (kot(data) > kot(cur->_data))
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
cur = new Node(data);
// 判断该插入parent的哪边
if (kot(data) < kot(parent->_data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
// 插入结束
// 保持平衡
while (parent && parent->_col == RED) // 出现连续的红节点
{
Node* grandParent = parent->_parent;
assert(grandParent);
if (grandParent->_left == parent) // parent在祖父节点左边
{
Node* uncle = grandParent->_right;
// u为红色,一定要提前判断u是否存在
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandParent->_col = RED;
if (grandParent == _root)
{
grandParent->_col = BLACK;
return true;
}
else // grandParent不是根节点,但其父节点为黑色,也插入完成
{
if (grandParent->_parent && grandParent->_parent->_col == BLACK)
{
return true;
}
else // grandParent的父节点为红,出现连续红节点,更新节点,继续调整
{
cur = grandParent;
parent = cur->_parent;
}
}
} // end of if (uncle && uncle->_col == RED)
else // u不存在或者为黑
{
// cur在p的左边
if (cur == parent->_left)
{
RotateR(grandParent);
grandParent->_col = RED;
parent->_col = BLACK;
}
else // cur在p的右边,需要旋转成左边的情况
{
RotateL(parent);
RotateR(grandParent);
cur->_col = BLACK;
grandParent->_col = RED;
}
return true;
}
} // end of - if (grandParent->_left == parent)
else // p在grandParent的右边
{
Node* uncle = grandParent->_left;
assert(grandParent);
// u为红色
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandParent->_col = RED;
if (grandParent == _root)
{
_root->_col = BLACK;
return true;
}
else
{
if (grandParent->_parent->_col == BLACK)
{
return true;
}
// 更新继续调整
else
{
cur = grandParent;
parent = cur->_parent;
}
}
} // end of if (uncle && uncle->_col == RED)
else // u不存在或者为黑
{
// cur在p的右边
if (cur == parent->_right)
{
RotateL(grandParent);
grandParent->_col = RED;
parent->_col = BLACK;
}
else // cur在p的右边,需要旋转成左边的情况
{
RotateR(parent);
RotateL(grandParent);
cur->_col = BLACK;
grandParent->_col = RED;
}
return true;
}
} // end of - else
}// end if - while
return true;
}
template <class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::RotateL(Node* parent)
{
KeyOfT kot;
Node* subR = parent->_right;
Node* subRL = subR->_left;
subR->_left = parent;
parent->_right = subRL;
Node* pparent = parent->_parent;
parent->_parent = subR;
if (subRL)
subRL->_parent = parent;
if (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else // 该子树是树的一部分
{
subR->_parent = pparent;
if (kot(subR)->_data < kot(pparent->_data))
{
pparent->_left = subR;
}
else
{
pparent->_right = subR;
}
}
}
template <class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::RotateR(Node* parent)
{
KeyOfT kot;
Node* subL = parent->_left;
Node* subLR = subL->_right;
subL->_right = parent;
parent->_left = subLR;
Node* pparent = parent->_parent;
parent->_parent = subL;
if (subLR)
subLR->_parent = parent;
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
subL->_parent = pparent;
if (kot(subL->_data) < kot(pparent->_data))
{
pparent->_left = subL;
}
else
{
pparent->_right = subL;
}
}
}
template <class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::_Inorder(Node* root)
{
KeyOfT kot;
if (root == nullptr)
return;
_Inorder(root->_left);
cout << root->kot(root->_data) << ' ';
_Inorder(root->_right);
}
改造部分大多是将比较数据套上仿函数
红黑树迭代器的结构和链表的迭代器类似,模板参数都有三个,T为节点中存储数据的类型,Ref为节点数据的引用,Ptr为节点中数据的指针。STL库中的红黑树实现了头节点,头节点的left指向树中最小节点,right指向树中最大节点,但实现头节点要付出较大的代价,在节点有了parent指针后,可以直接模拟中序进行++,–的操作。
++就是找比当前节点大的节点,翻译一下就是当前节点右树的最左节点。如果当前节点无右树,向上找parent,如果当前节点是parent的左孩子,那么parent就是比当前节点大的节点;如果当前节点是parent的右孩子,说明当前节点大于parent,将当前节点更新为parent继续向上找,直到当前节点是parent的左孩子。
–同理
1.左孩子存在,返回左树的最大节点
2.左孩子不存在,如果当前节点是parent的右孩子,返回parent
3.左孩子不存在,当前节点是parent的左孩子,向上更新,直到当前节点是parent的右孩子
template <class T, class Ref, class Ptr>
typename RBTreeIterator<T, Ref, Ptr>::self& RBTreeIterator<T, Ref, Ptr>::operator++()
{
if (_node->_right) // 右孩子存在
{
_node = _node->_right;
while (_node->_left)
{
_node = _node->_left;
}
}
else
{
while (_node->_parent && _node == _node->_parent->_right) // 如果父节点存在并且当前节点是父节点的右孩子,要继续更新
{
_node = _node->parent;
}
_node = _node->_parent;
}
return *this;
}
template <class T, class Ref, class Ptr>
typename RBTreeIterator<T, Ref, Ptr>::self RBTreeIterator<T, Ref, Ptr>::operator++(int)
{
self tmp = *this;
++(*this);
return tmp;
}
template <class T, class Ref, class Ptr>
typename RBTreeIterator<T, Ref, Ptr>::self& RBTreeIterator<T, Ref, Ptr>::operator--()
{
if (_node->_left) // 右孩子存在
{
_node = _node->_left;
while (_node->_right)
{
_node = _node->_right;
}
}
else
{
while (_node->_parent && _node == _node->_parent->_left) // 如果父节点存在并且当前节点是父节点的右孩子,要继续更新
{
_node = _node->parent;
}
_node = _node->_parent;
}
return *this;
}
template <class T, class Ref, class Ptr>
typename RBTreeIterator<T, Ref, Ptr>::self RBTreeIterator<T, Ref, Ptr>::operator--(int)
{
self tmp = *this;
--(*this);
return tmp;
}
#pragma once
#include
using namespace std;
#include
#include
enum Colour
{
RED,
BLACK
};
template <class T>
struct RBTreeNode
{
T _data;
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
Colour _col;
RBTreeNode(T data)
:_data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _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)
{}
Ref operator*() { return _node->_data; }
Ptr operator->() { return &(_node->_data); }
self& operator++();
self operator++(int);
self& operator--();
self operator--(int);
bool operator!=(self& s) { return s._node != _node; }
Node* _node;
};
template <class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, T&, T*> iterator;
typedef RBTreeIterator<T, const T&, const T*> const_iterator;
public:
pair<iterator, bool> Insert(const T& data);
iterator begin()
{
Node* cur = _root;
while (cur->_left)
{
cur = cur->_left;
}
return iterator(cur);
}
iterator end() { return iterator(nullptr); }
const_iterator begin() const
{
Node* cur = _root;
while (cur->_left)
{
cur = cur->_left;
}
return const_iterator(cur);
}
const_iterator end() const { return const_iterator(nullptr); }
void Inorder() { _Inorder(_root); }
private:
void RotateL(Node* parent);
void RotateR(Node* parent);
void _Inorder(Node* root);
private:
Node* _root = nullptr;
};
template <class K, class T, class KeyOfT>
pair<typename RBTree<K, T, KeyOfT>::iterator, bool> RBTree<K, T, KeyOfT>::Insert(const T& data)
{
KeyOfT kot;
// 以搜索二叉树的规则插入
if (_root == nullptr)
{
_root = new Node(data);
// 根节点为黑色
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
Node* cur = _root;
Node* parent = nullptr;
// 找合适的插入位置
while (cur)
{
if (kot(data) < kot(cur->_data))
{
parent = cur;
cur = cur->_left;
}
else if (kot(data) > kot(cur->_data))
{
parent = cur;
cur = cur->_right;
}
else
{
return make_pair(iterator(cur), false);
}
}
cur = new Node(data);
// 判断该插入parent的哪边
if (kot(data) < kot(parent->_data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
// 插入结束
// 保持平衡
while (parent && parent->_col == RED) // 出现连续的红节点
{
Node* grandParent = parent->_parent;
assert(grandParent);
if (grandParent->_left == parent) // parent在祖父节点左边
{
Node* uncle = grandParent->_right;
// u为红色,一定要提前判断u是否存在
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandParent->_col = RED;
if (grandParent == _root)
{
grandParent->_col = BLACK;
return make_pair(iterator(cur), true);
}
else // grandParent不是根节点,但其父节点为黑色,也插入完成
{
if (grandParent->_parent && grandParent->_parent->_col == BLACK)
{
return make_pair(iterator(cur), true);
}
else // grandParent的父节点为红,出现连续红节点,更新节点,继续调整
{
cur = grandParent;
parent = cur->_parent;
}
}
} // end of if (uncle && uncle->_col == RED)
else // u不存在或者为黑
{
pair<iterator, bool> ret = make_pair(iterator(cur), true);
// cur在p的左边
if (cur == parent->_left)
{
RotateR(grandParent);
grandParent->_col = RED;
parent->_col = BLACK;
}
else // cur在p的右边,需要旋转成左边的情况
{
RotateL(parent);
RotateR(grandParent);
cur->_col = BLACK;
grandParent->_col = RED;
}
return ret;
}
} // end of - if (grandParent->_left == parent)
else // p在grandParent的右边
{
Node* uncle = grandParent->_left;
assert(grandParent);
// u为红色
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandParent->_col = RED;
if (grandParent == _root)
{
_root->_col = BLACK;
return make_pair(iterator(cur), true);
}
else
{
if (grandParent->_parent->_col == BLACK)
{
return make_pair(iterator(cur), true);
}
// 更新继续调整
else
{
cur = grandParent;
parent = cur->_parent;
}
}
} // end of if (uncle && uncle->_col == RED)
else // u不存在或者为黑
{
pair<iterator, bool> ret = make_pair(iterator(cur), true);
// cur在p的右边
if (cur == parent->_right)
{
RotateL(grandParent);
grandParent->_col = RED;
parent->_col = BLACK;
}
else // cur在p的右边,需要旋转成左边的情况
{
RotateR(parent);
RotateL(grandParent);
cur->_col = BLACK;
grandParent->_col = RED;
}
return ret;
}
} // end of - else
}// end if - while
return make_pair(iterator(cur), true);
}
template <class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::RotateL(Node* parent)
{
KeyOfT kot;
Node* subR = parent->_right;
Node* subRL = subR->_left;
subR->_left = parent;
parent->_right = subRL;
Node* pparent = parent->_parent;
parent->_parent = subR;
if (subRL)
subRL->_parent = parent;
if (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else // 该子树是树的一部分
{
subR->_parent = pparent;
if (kot(subR->_data) < kot(pparent->_data))
{
pparent->_left = subR;
}
else
{
pparent->_right = subR;
}
}
}
template <class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::RotateR(Node* parent)
{
KeyOfT kot;
Node* subL = parent->_left;
Node* subLR = subL->_right;
subL->_right = parent;
parent->_left = subLR;
Node* pparent = parent->_parent;
parent->_parent = subL;
if (subLR)
subLR->_parent = parent;
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
subL->_parent = pparent;
if (kot(subL->_data) < kot(pparent->_data))
{
pparent->_left = subL;
}
else
{
pparent->_right = subL;
}
}
}
template <class K, class T, class KeyOfT>
void RBTree<K, T, KeyOfT>::_Inorder(Node* root)
{
KeyOfT kot;
if (root == nullptr)
return;
_Inorder(root->_left);
cout << kot(root->_data) << ' ';
_Inorder(root->_right);
}
template <class T, class Ref, class Ptr>
typename RBTreeIterator<T, Ref, Ptr>::self& RBTreeIterator<T, Ref, Ptr>::operator++()
{
if (_node->_right) // 右孩子存在
{
_node = _node->_right;
while (_node->_left)
{
_node = _node->_left;
}
}
else
{
while (_node->_parent && _node == _node->_parent->_right) // 如果父节点存在并且当前节点是父节点的右孩子,要继续更新
{
_node = _node->_parent;
}
_node = _node->_parent;
}
return *this;
}
template <class T, class Ref, class Ptr>
typename RBTreeIterator<T, Ref, Ptr>::self RBTreeIterator<T, Ref, Ptr>::operator++(int)
{
self tmp = *this;
++(*this);
return tmp;
}
template <class T, class Ref, class Ptr>
typename RBTreeIterator<T, Ref, Ptr>::self& RBTreeIterator<T, Ref, Ptr>::operator--()
{
if (_node->_left) // 右孩子存在
{
_node = _node->_left;
while (_node->_right)
{
_node = _node->_right;
}
}
else
{
while (_node->_parent && _node == _node->_parent->_left) // 如果父节点存在并且当前节点是父节点的右孩子,要继续更新
{
_node = _node->parent;
}
_node = _node->_parent;
}
return *this;
}
template <class T, class Ref, class Ptr>
typename RBTreeIterator<T, Ref, Ptr>::self RBTreeIterator<T, Ref, Ptr>::operator--(int)
{
self tmp = *this;
--(*this);
return tmp;
}
template <class K>
class Set
{
struct KeyOfSet
{
const K& operator()(const K& data)
{
return data;
}
};
public:
typedef RBTreeIterator<K, const K&, const K*> iterator;
typedef RBTreeIterator<K, const K&, const K*> const_iterator;
iterator begin() const{ return _t.begin(); }
iterator end() const{ return _t.end(); }
pair<iterator, bool> Insert(const K& k)
{
pair<RBTreeIterator<K, K&, K*>, bool> p = _t.Insert(k);
return pair<iterator, bool>(iterator(p.first._node), p.second);
}
void Inorder() { _t.Inorder(); }
private:
typedef RBTree<K, K, KeyOfSet> RBTree;
RBTree _t;
};
template <class K, class V>
class Map
{
struct KeyOfMap
{
const K& operator()(const pair<K, V>& data)
{
return data.first;
}
};
public:
typedef RBTreeIterator<pair<K, V>, pair<K, V>&, pair<K, V>*> iterator;
typedef RBTreeIterator<const pair<K, V>, const pair<K, V>&, const pair<K, V>*> const_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(); }
pair<iterator, bool> Insert(const pair<K, V>& kv) { return _t.Insert(kv); }
void Inorder() { _t.Inorder(); }
V& operator[](const K& k)
{
pair<K, V> p(k, V());
pair<iterator, bool> ret = _t.Insert(p);
return ret.first->second;
}
private:
typedef RBTree<K, pair<K, V>, KeyOfMap> RBTree;
RBTree _t;
};
两者的接口大多是复用红黑树的接口,其中map要实现[]的重载:先根据key值构造一个键值对,该键值对的value值是默认值,然后将键值对插入得到返回的pair,函数最后返回插入得到的pair的first的value引用(pair的first为map的迭代器)