全文目录
- map和set
- 红黑树的封装
- 红黑树的迭代器
- begin() 和 end()
- operator++()
- operator--()
- map完整代码
- set完整代码
- 改造后的红黑树代码
map和set
map和set 是STL中的容器,两者底层的实现都是参考文档:
map参考文档
set参考文档
两个容器底层都是去重的二叉搜索树实现的,一般使用高效的红黑树通过封装来实现。
红黑树的封装
先看一下原码:
在STL的原码中红黑树是有两个数据类型的树,map和set是通过控制模板类型的传递来生成不同数据类型的红黑树。
map传递:key 和 pair<key, value>
set传递: key 和 key
但是这样有导致了红黑树比较时不知道是使用单类型还是pair类来进行的比较,所以在参数传递时还会将传递仿函数,指定使用key进行比较
map的比较仿函数:
template<typename K, typename V>
struct MapValueOfT
{
const K& operator()(const pair<K, V>& kv) const
{
return kv.first;
}
};
set的比较类仿函数:
template<typename K>
struct SetValueOfT
{
const K& operator()(const K& key) const
{
return key;
}
};
那么在两者内部,红黑树都是这样的结构:
map的底层红黑树:
template<typename K, typename V>
class map
{
public:
typedef pair<K, V> valueType;
typedef RBTree<K, valueType, MapValueOfT<K, V>> Tree;
Tree _t;
}
set底层的红黑树:
template<typename K>
class set
{
public:
typedef K valueType;
typedef RBTree<K, valueType, SetValueOfT<K>> Tree;
Tree _t;
}
红黑树的迭代器
begin() 和 end()
STL明确规定,begin()
与end()
代表的是一段前闭后开的区间,而对红黑树进行中序遍历后,可以得到一个有序的序列,因此:begin()
可以放在红黑树中最小节点(即最左侧节点)的位置,end()
放在最大节点(最右侧节点)的下一个位置,关键是最大节点的下一个位置在哪块?
能否给成nullptr
呢?答案是行不通的,因为对end()
位置的迭代器进行–操作,必须要能找最后一个元素,此处就不行,因此最好的方式是将end()
放在头结点的位置:
但是实现的红黑树的头结点是nullptr
,我们只实现正向的迭代器:
operator++()
找迭代器的下一个节点,因为是中序遍历,所以分两种情况:
- 右子树存在
找右子树的最左节点
- 右子树不存在
右子树不存在,向上查找,直到
cur != parent->_right
Self& operator++()
{
// 右子树不为空,就是找右子树中的最左节点
if (_node->_right)
{
_node = _node->_right;
while (_node->_left)
{
_node = _node->_left;
}
}
else
{
// 右子树为空,找孩子不是父亲的右节点的父节点
Node* parent = _node->_parent;
while (parent && parent->_right == _node)
{
_node = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
operator–()
获取中序遍历的前一个节点,同样分两种情况:
- 左子树存在
在左子树中找最大的节点,即左子树中最右侧节点
- 左子树不存在
左子树不存在,向上查找,直到
cur != parent->_left
Self& operator--()
{
// 左子树不为空,找左子树中的最右节点
if (_node->_left)
{
_node = _node->_left;
while (_node && _node->_left)
{
_node = _node->_left;
}
}
else
{
// 左子树为空,找孩子不是父亲的左节点的父节点
Node* parent = _node->_parent;
while (parent && parent->_left == _node)
{
_node = parent;
parent = parent->_parent;
}
}
return *this;
}
map完整代码
template<typename K, typename V>
struct MapValueOfT
{
const K& operator()(const pair<K, V>& kv) const
{
return kv.first;
}
};
template<typename K, typename V>
class map
{
public:
typedef pair<K, V> valueType;
typedef RBTree<K, valueType, MapValueOfT<K, V>> Tree;
typedef typename RBTree<K, valueType, MapValueOfT<K, V>>::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);
}
void inorder()
{
_t.InOrder();
}
V& operator[](const K& key)
{
return (insert(make_pair(key, V())).first)->second;
}
Tree _t;
};
set完整代码
template<typename K>
struct SetValueOfT
{
const K& operator()(const K& key) const
{
return key;
}
};
template<typename K>
class set
{
public:
typedef K valueType;
typedef RBTree<K, valueType, SetValueOfT<K>> Tree;
typedef typename RBTree<K, valueType, SetValueOfT<K>>::iterator iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
pair<iterator, bool> insert(const K& key)
{
return _t.Insert(key);
}
void inorder()
{
_t.InOrder();
}
Tree _t;
};
改造后的红黑树代码
enum Color
{
BLACK,
RED
};
template<typename T>
struct RBNode
{
RBNode(const T& data)
: _data(data)
, _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _col(RED)
{}
RBNode<T>* _left;
RBNode<T>* _right;
RBNode<T>* _parent;
Color _col;
T _data;
};
template<typename T, typename Ref, typename Ptr>
class Iterator
{
public:
typedef RBNode<T> Node;
typedef Iterator<T, Ref, Ptr> Self;
Iterator(Node* node)
:_node(node)
{}
bool operator==(const Self& it) const
{
return _node == it._node;
}
bool operator!=(const Self& it) const
{
return _node != it._node;
}
T& operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &(_node->_data);
}
Self& operator++()
{
// 右子树不为空,就是找右子树中的最左节点
if (_node->_right)
{
_node = _node->_right;
while (_node->_left)
{
_node = _node->_left;
}
}
else
{
// 右子树为空,找孩子不是父亲的右节点的父节点
Node* parent = _node->_parent;
while (parent && parent->_right == _node)
{
_node = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self& operator--()
{
// 左子树不为空,找左子树中的最右节点
if (_node->_left)
{
_node = _node->_left;
while (_node && _node->_left)
{
_node = _node->_left;
}
}
else
{
// 左子树为空,找孩子不是父亲的左节点的父节点
Node* parent = _node->_parent;
while (parent && parent->_left == _node)
{
_node = parent;
parent = parent->_parent;
}
}
return *this;
}
Self operator++(int)
{
Self tmp(_node);
this->operator++();
return tmp;
}
Self operator--(int)
{
Self tmp(_node);
operator--();
return tmp;
}
private:
Node* _node;
};
template<typename Key, typename Value, typename ValueOfT = less<Key>>
class RBTree
{
public:
typedef RBNode<Value> Node;
typedef Iterator<Value, Value&, Value*> iterator;
RBTree()
: _root(nullptr)
{}
iterator begin()
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return iterator(cur);
}
iterator end()
{
return iterator(nullptr);
}
pair<iterator, bool> Insert(const Value& data)
{
// 空树的插入
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(_root, true);
}
// 非空树的插入
Node* parent = nullptr;
Node* cur = _root;
// 寻找插入的位置
while (cur)
{
parent = cur;
if (cmp(data) > cmp(cur->_data))
{
cur = cur->_right;
}
else if (cmp(data) < cmp(cur->_data))
{
cur = cur->_left;
}
else // 找到重复元素,插入失败
{
return make_pair(cur, false);
}
}
// 开始插入
cur = new Node(data);
if (cmp(data) > cmp(parent->_data))
{
cur->_parent = parent;
parent->_right = cur;
}
else
{
cur->_parent = parent;
parent->_left = cur;
}
Node* newNode = cur;
// 如果父节点是根节点,那么它的颜色一定是要黑色,不然在前面插入的时候已经出错了
// 所以进入循环,就说明一定存在祖父节点
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED) // 叔叔存在且为红,继续往上更新
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
}
else // 叔叔不存在或者叔叔为黑
{
if (cur == parent->_left) // 右单旋
{
// g
// / \
// p u
// /
// c
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else // 左右双旋
{
// g
// / \
// p u
// \
// c
//RotateL(parent);
//RotateR(grandfather);
RotateLR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else if (parent == grandfather->_right)
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED) // 叔叔存在且为红,继续往上更新
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
}
else // 叔叔不存在或者叔叔为黑
{
if (cur == parent->_right) // 左单旋
{
// g
// / \
// u p
// \
// c
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else // 右左双旋
{
// g
// / \
// u p
// /
// c
//RotateR(parent);
//RotateL(grandfather);
RotateRL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;
return make_pair(newNode, true);
}
void InOrder()
{
_InOrder(_root);
}
// 根据黑色节点数量判断是否满足红黑树条件
bool IsBalance()
{
if (_root && _root->_col == RED)
{
puts("root的颜色为红!!!");
return false;
}
int balanceNum = 0;
return Check(_root, balanceNum, 0);
}
private:
// 前序遍历检查每天路径上的黑色节点数量
bool Check(Node* root, int& balanceNum, int blackNum)
{
if (root == nullptr)
{
if (balanceNum == 0)
{
balanceNum = blackNum;
return true;
}
else
{
if (blackNum == balanceNum)
return true;
else
return false;
}
}
if (root->_col == BLACK)
{
blackNum++;
}
return Check(root->_left, balanceNum, blackNum)
&& Check(root->_right, balanceNum, blackNum);
}
void _InOrder(Node* root)
{
if (root == nullptr)
return;
_InOrder(root->_left);
cout << root->_data.first << " : " << root->_data.second << endl;
_InOrder(root->_right);
}
// 左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* pparent = parent->_parent;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
parent->_parent = subR;
subR->_left = parent;
subR->_parent = pparent;
if (pparent)
{
if (pparent->_left == parent)
pparent->_left = subR;
else
pparent->_right = subR;
}
else
_root = subR;
}
// 右单旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* pparent = parent->_parent;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
parent->_parent = subL;
subL->_right = parent;
subL->_parent = pparent;
if (pparent)
{
if (pparent->_left == parent)
pparent->_left = subL;
else
pparent->_right = subL;
}
else
_root = subL;
}
// 左右双旋
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
RotateL(subL);
RotateR(parent);
}
// 右左双旋
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
RotateR(subR);
RotateL(parent);
}
ValueOfT cmp;
Node* _root;
};