目录
一、前言
二、标准源码分析
三、泛型红黑树
1、结点
2、红黑树框架
3、set框架
4、map框架
四、仿函数
五、迭代器
六、红黑树代码
七、set的封装
八、map的封装
在标准库中map和set的底层结构是使用红黑树来实现的。但是,map是key,value类型的容器,set是key类型的容器,那我们是不是要分别写一个 kv类型的红黑树和key类型的红黑树去分别封装呢?还是说可以使用同一棵树去实现呢?
下面我们从标准库源码去看一看它是怎么封装的。
我们直接上源码
从上面的源码中,我们看出:
1、set 和 map 的红黑树结构都有两个模板参数:key_type 和 value_type。
2、set 的红黑树结构的 key_type 和 value_type的本质都是key。
3、map 的红黑树结构的 key_type 和 value_type 分别是 key 和 pair。
* 而红黑树结点所存数据类型是由模板参数 value 来控制的。即通过vlaue 我们可以知道红黑树存储的是key类型的set,还是pair类型的map。
即一棵泛型结构的红黑树,通过不同实例化参数,实现出了map和set。
为了实现结点的泛型,我们可以直接使用一个模板参数T,这样T既可以是key类型,也可以是pair
enum Colour
{
RED,
BLACK
};
template
struct RBTreeNode
{
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
//pair _kv;
T _data;
Colour _col;
RBTreeNode(const T& data, Colour col = RED)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
, _col(col)
{}
};
对于T模板参数可能是键值Key,也可能是由Key和Value共同构成的键值对。
template
struct RBTree
{
typedef RBTreeNode Node;
private:
Node* _root = nullptr;
}
如果是set容器,那么它传入底层红黑树的模板参数就是Key和Key。
template
class set
{
private:
RBTree _t;
};
如果是map容器,传入底层红黑树的模板参数就是Key和Key和value的键值对。
class map
{
private:
RBTree> _t;
};
红黑树变成泛型后就出现了一个问题:插入的时候data的大小如何去进行比较呢?我们并不知道是什么类型,是key,还是pair的比较,而我们刚开始kv结构就直接用kv.first去比较了。但是现在我们并不能确定它到底是哪种类型。对于set是Key,可以比较,对于map是pair,那我们要取其中的first来比较。
那么这里,我们就需要一个仿函数来帮助我们解决这个问题了。所以正确的红黑树框架如下:
template
struct RBTree
{
typedef RBTreeNode Node;
private:
Node* _root = nullptr;
};
其中第三个模板参数就是我们要自己实现的一个仿函数。
template
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
private:
RBTree _t;
};
template
class map
{
struct MapKeyOfT
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
public:
private:
RBTree, MapKeyOfT> _t;
};
因此我们红黑树的插入的查找部分就可以使用仿函数来实现。
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 false;
}
}
cur = new Node(data);
Node* newnode = cur;
if (kot(parent->_data) > kot(data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
迭代器的定义:
template
struct __RBIterator
{
typedef RBTreeNode Node;
typedef __RBIterator RBIterator;
Node* _node;
__RBIterator(const 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) const
{
return _node == s._node;
}
++的重载
1、右子树不为空,++就是找右子树中序第一个(最左节点)
2、右子树为空,++找孩子是父亲左的那个祖先。
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 && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
--的重载
对于–,如果是根,–就是左子树,找到左子树最大的那一个(最右节点)
1、如果节点的左子树不为空,--找左子树最右的节点。
2、如果节点的左子树为空,--找祖先(孩子是父亲的右的祖先)。
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 = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
有了上面的迭代器模板,我们就可以实现红黑树的迭代器了
template
class RBTree
{
typedef RBTreeNode Node;
public:
typedef __RBTreeIterator iterator;
iterator begin()
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
};
template
struct RBTree
{
typedef RBTreeNode Node;
public:
typedef _RBIterator iterator;
typedef _RBIterator const_iterator;
iterator begin()
{
Node* left = _root;
while (left && left->_left)
{
left = left->_left;
}
return iterator(left);
}
iterator end()
{
return iterator(nullptr);
}
pair 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(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;
if (kot(parent->_data) > kot(data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
assert(grandfather);
assert(grandfather->_col == BLACK);
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
//继续往上处理
cur = grandfather;
parent = cur->_parent;
}
// uncle 不存在 + 存在且为黑
else
{
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
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
//继续往上处理
cur = grandfather;
parent = cur->_parent;
}
else
{
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);
}
private:
void RotateL(Node* parent) //左单旋
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* pparent = parent->_parent;
subR->_left = parent;
parent->_parent = subR;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
if (parent == _root)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (pparent->_left == parent)
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;
parent->_parent = subL;
subL->_right = parent;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
if (parent == _root)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (pparent->_left == parent)
pparent->_left = subL;
else
pparent->_right = subL;
subL->_parent = pparent;
}
}
private:
Node* _root = nullptr;
};
#pragma once
#include"RBTree.h"
namespace zdl
{
template
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
//typename:没有实例化的模板,区分不了是静态变量还是类型,typename告诉编译器是类型
typedef typename RBTree::iterator iterator;
iterator begin()
{
_t.begin();
}
iterator end()
{
_t.end();
}
pair insert(const K& key)
{
return _t.insert(key);
}
private:
RBTree _t;
};
}
#pragma once
#include"RBTree.h"
namespace zdl
{
template
class map
{
struct MapKeyOfT
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
public:
typedef typename RBTree, MapKeyOfT>::iterator iterator;
iterator begin()
{
_t.begin();
}
iterator end()
{
_t.end();
}
pair insert(const pair& kv)
{
return _t.insert(kv);
}
V& operator[](const K& key)const
{
pair ret = insert(make_pair(K, V()));
return ret.first->second;
}
private:
RBTree, MapKeyOfT> _t;
};
}