C++知识点 – 使用红黑树封装map和set
文章目录
RBTree是通过第二个模板参数Value来区分map和set的,模板参数K的存在是为了实现find;
一、RBTree.h
1.结构
(1)RBTree的节点需要作出更改,由于节点中存放的数据类型不确定,就统一用模板参数T代替;
(2)Insert中的比较大小需要使用_data进行比较,但是_data对于map和set是不同的类型,就需要使用仿函数进行控制,因此RBTree的模板参数中还需要传一个仿函数KeyOfT,用于取出T类型中的key值;
enum color
{
RED,
BLACK
};
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
color _col;
RBTreeNode(const T& data)
: _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
{}
};
template<class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
private:
Node* _root = nullptr;
};
2.Insert
(1)需要使用仿函数KeyOfT对Insert进行重写,每一个需要取K的地方都使用仿函数;
(2)insert返回一个pair<iterator, bool>,若key不存在,就插入,并返回该位置的迭代器,若存在,就返回已存在元素位置的迭代器;
pair<iterator, bool> Insert(const T& data)
{
KeyOfT kot;
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
Node* parent = nullptr;
Node* cur = _root;
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);
Node* newnode = cur;//由于需要返回新插入结点的迭代器,而且后面的操作可能使cur偏离原来的位置,所以需要记录新节点
cur->_col = RED;
if (kot(data) < kot(parent->_data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
while (parent && parent->_col == RED)//parent存在且为红,则违反规则
{
Node* grandfather = parent->_parent;
assert(grandfather);
assert(grandfather->_col == BLACK);//祖父存在且为黑
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;
}
//情况2、3:uncle不存在 + 存在且为黑
else
{
//情况2:cur、p、g成一条直线
if (cur == parent->_left)
{
//右单旋+变色
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
//情况3:cur、p、g成一条折线
else
{
//左右单旋+变色
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_left;
//情况1:uncle存在且为红
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
//继续往上处理
cur = grandfather;
parent = cur->_parent;
}
//情况2、3:uncle不存在 + 存在且为黑
else
{
//情况2:cur、p、g成一条直线
if (cur == parent->_right)
{
//左单旋+变色
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
//情况3:cur、p、g成一条折线
else
{
//右左单旋+变色
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;//根节点一定是黑色
return make_pair(iterator(newnode), true);
}
3.迭代器
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;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator==(const Self& s)
{
return _node == s._node;
}
};
operator++
Self& operator++()
{
//若右子树不为空,则++找的就是右子树中最左节点
if (_node->_right)
{
Node* left = _node->_right;
while (left->_left)
{
left = left->_left;
}
_node = left;
}
//右子树为空,则++找的是孩子不是父亲右的那个祖先
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while (parent && parent->_right == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
operator–
Self& operator--()
{
//若右子树不为空,则++找的就是右子树中最右节点
if (_node->_right)
{
Node* right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right;
}
//右子树为空,则++找的是孩子不是父亲左的那个祖先
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while (parent && parent->_left == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
RBTree类中的begin和end:
template<class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef __RBTreeIterator<T, T&, T*> iterator;
iterator begin()//找整棵树的最左节点
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()//返回空指针构造的迭代器
{
return iterator(nullptr);
}
private:
Node* _root = nullptr;
};
RBTree.h
#pragma once
enum color
{
RED,
BLACK
};
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
color _col;
RBTreeNode(const T& data)
: _left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _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;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
bool operator==(const Self& s)
{
return _node == s._node;
}
Self& operator++()
{
//若右子树不为空,则++找的就是右子树中最左节点
if (_node->_right)
{
Node* left = _node->_right;
while (left->_left)
{
left = left->_left;
}
_node = left;
}
//右子树为空,则++找的是孩子不是父亲右的那个祖先
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while (parent && parent->_right == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self& operator--()
{
//若右子树不为空,则++找的就是右子树中最右节点
if (_node->_right)
{
Node* right = _node->_left;
while (right->_right)
{
right = right->_right;
}
_node = right;
}
//右子树为空,则++找的是孩子不是父亲左的那个祖先
else
{
Node* parent = _node->_parent;
Node* cur = _node;
while (parent && parent->_left == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
};
template<class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef __RBTreeIterator<T, T&, T*> iterator;
iterator begin()//找整棵树的最左节点
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()//返回空指针构造的迭代器
{
return iterator(nullptr);
}
pair<iterator, bool> Insert(const T& data)
{
KeyOfT kot;
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
Node* parent = nullptr;
Node* cur = _root;
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);
Node* newnode = cur;//由于需要返回新插入结点的迭代器,而且后面的操作可能使cur偏离原来的位置,所以需要记录新节点
cur->_col = RED;
if (kot(data) < kot(parent->_data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
while (parent && parent->_col == RED)//parent存在且为红,则违反规则
{
Node* grandfather = parent->_parent;
assert(grandfather);
assert(grandfather->_col == BLACK);//祖父存在且为黑
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;
}
//情况2、3:uncle不存在 + 存在且为黑
else
{
//情况2:cur、p、g成一条直线
if (cur == parent->_left)
{
//右单旋+变色
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
//情况3:cur、p、g成一条折线
else
{
//左右单旋+变色
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_left;
//情况1:uncle存在且为红
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
//继续往上处理
cur = grandfather;
parent = cur->_parent;
}
//情况2、3:uncle不存在 + 存在且为黑
else
{
//情况2:cur、p、g成一条直线
if (cur == parent->_right)
{
//左单旋+变色
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
//情况3:cur、p、g成一条折线
else
{
//右左单旋+变色
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK;//根节点一定是黑色
return make_pair(iterator(newnode), true);
}
void InOrder()
{
_InOrder(_root);
}
bool IsBalance()
{
if (_root == nullptr)
{
return true;
}
if (_root->_col == RED)
{
cout << "根节点不是黑色" << endl;
return false;
}
int benchmark = 0;//黑色节点数量基准值
//Node* cur = _root;
//while (cur)//首先算出一条路径上的黑色节点数量作为基准值
//{
// if (cur->_col == BLACK)
// {
// ++benchmark;
// }
// cur = cur->_left;
//}
return PrevCheck(_root, 0, benchmark);
}
private:
bool PrevCheck(const Node* root, int blackNum, int& benchmark)//前序检查
{
if (root == nullptr)//走到叶子节点了,该条路径走完
{
if (benchmark == 0)//在第一条前序路径走完后,黑色节点数量作为基准
{
benchmark = blackNum;
return true;
}
if (blackNum != benchmark)
{
cout << "某条路径上黑色节点数量不相等" << endl;
return false;
}
else
{
return true;
}
}
if (root->_col == BLACK)
{
++blackNum;
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "出现连续红色节点" << endl;
return false;
}
return PrevCheck(root->_left, blackNum, benchmark)
&& PrevCheck(root->_right, blackNum, benchmark);
}
void _InOrder(const Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;
_InOrder(root->_right);
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* ppNode = parent->_parent;//指向parent的父节点
parent->_right = subRL;
if (subRL)//subRL可能为空,需要判断一下
{
subRL->_parent = parent;
}
subR->_left = parent;
parent->_parent = subR;
if (parent == _root)//若parent是整棵树的根节点
{
_root = subR;
subR->_parent = nullptr;
}
else//parent是子树的根节点
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
}
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* ppNode = parent->_parent;
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
subL->_right = parent;
parent->_parent = subL;
if (parent == _root)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
private:
Node* _root = nullptr;
};
二、map.h
1.结构
map中的RBTree的第二个模板参数T传的是pair<K, V>;
仿函数MapKeyOfT是用来取出pair中的K的;
template<class K, class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t;
};
2.Insert
pair<iterator, bool> insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
3.迭代器封装
public:
typedef typename RBTree<K, pair<K, V>, MapKeyOfT>::iterator iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
重定义一个类模板中已经定义的类型,在typedef后需再加一个typename;
typename是告诉编译器这是类型名,不是静态变量名(因为静态变量也可以这样直接从类域中取);
4.operator[ ]
operator[ ]是只有KV模型有的;
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.Insert(make_pair(key, V()));
return ret.first->second;
}
map.h
template<class K, class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
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);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = insert(make_pair(key, V()));
return ret.first->second;
}
private:
RBTree<K, pair<K, V>, MapKeyOfT> _t;
};
三、set.h
1.结构
map中的RBTree的第二个模板参数T传的是K;
仿函数SetKeyOfT是用来返回K的;
template<class K, class V>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
private:
RBTree<K, pair<K, V>, SetKeyOfT> _t;
};
2.Insert
pair<iterator, bool> insert(const K& key)
{
return _t.Insert(key);
}
3.迭代器封装
public:
typedef typename RBTree<K, K, SetKeyOfT>::iterator iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
set.h
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
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);
}
private:
RBTree<K, K, SetKeyOfT> _t;
};