目录
一、红黑树的完善:
1、红黑树节点模版的修改:
2、仿函数在模拟实现中的应用:
3、新增迭代器:
4、红黑树中的迭代器实现:
二、set与map的模拟实现:
1、insert:
2、map的[ ]:
三、测试:
四、完整代码:
红黑树初始代码:
#pragma once
#include<iostream>
using namespace std;
enum COLOR
{
RED,
BLACK
};
template<class K, class V>
struct RBTreeNode
{
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
pair<K, V> _kv;
COLOR col;
RBTreeNode(const pair<K, V>& kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _kv(kv)
, col(RED)
{}
};
template<class K, class V>
class RBTree
{
typedef RBTreeNode<K, V> Node;
public:
bool Insert(pair<K, V> kv)
{
//先进来判断这个树是不是空树
if (_root == nullptr)
{
_root = new Node(kv);
_root->col = BLACK;
return true;
}
Node* parent = nullptr;
Node* cur = _root;
//找到要插入的位置
while (cur)
{
if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else
{
return false;
}
}
//走到这就是找到了
cur = new Node(kv);
cur->col = RED;
//再连接到这个红黑树中
if (parent->_kv.first > cur->_kv.first)
{
parent->_left = cur;
}
else//parent->_kv.first < cur->_kv.first
{
parent->_right = cur;
}
cur->_parent = parent;
//已经连接完成后
while (parent && parent->col == RED)
{
//这里祖父必定存在,因为如果进循环后parent就是red,然而red不可能为根节点,所以parent的parent必定存在
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->col == RED)
{
//修改颜色
uncle->col = BLACK;
parent->col = BLACK;
grandfather->col = RED;
//修改cur
cur = grandfather;
//修改parent继续指向cur的parent
parent = cur->_parent;
}
else//uncle不存在或者uncle为黑色就需要旋转了
{
if (cur == parent->_left)
{
RotateR(grandfather);
parent->col = BLACK;
grandfather->col = RED;
}
else//cur == parent->_right
{
RotateL(parent);
RotateR(grandfather);
cur->col = BLACK;
grandfather->col = RED;
}
break;
}
}
else//parent == grandfather->_right
{
Node* uncle = grandfather->_left;
if (uncle && uncle->col == RED)
{
//修改颜色
uncle->col = BLACK;
parent->col = BLACK;
grandfather->col = RED;
//修改cur
cur = grandfather;
//修改parent继续指向cur的parent
parent = cur->_parent;
}
else//uncle不存在或者uncle为黑色就需要旋转了
{
if (cur == parent->_right)
{
RotateL(grandfather);
parent->col = BLACK;
grandfather->col = RED;
}
else//cur == parent->_right
{
RotateR(parent);
RotateL(grandfather);
cur->col = BLACK;
grandfather->col = RED;
}
break;
}
}
}
_root->col = BLACK;
return true;
}
//左单旋
void RotateL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
parent->_right = curleft;
if (curleft)
{
curleft->_parent = parent;
}
cur->_left = parent;
//将parent的父节点保存起来
Node* pparent = parent->_parent;
parent->_parent = cur;
if (parent == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (pparent->_kv.first < cur->_kv.first)
{
pparent->_right = cur;
}
else //if (pparent->_kv.first > cur->_kv.first)
{
pparent->_left = cur;
}
cur->_parent = pparent;
}
}
//右单旋
void RotateR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
parent->_left = curright;
if (curright)
{
curright->_parent = parent;
}
cur->_right = parent;
//将parent的父节点保存起来
Node* pparent = parent->_parent;
parent->_parent = cur;
if (parent == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (pparent->_kv.first < cur->_kv.first)
{
pparent->_right = cur;
}
else //if (pparent->_kv.first > cur->_kv.first)
{
pparent->_left = cur;
}
cur->_parent = pparent;
}
}
bool CheckColor(Node* root, int blacknum, int benchmark)
{
if (root == nullptr)
{
if (blacknum != benchmark)
{
cout << "黑色节点的数量不匹配" << endl;
return false;
}
return true;
}
if (root->col == BLACK)
{
++blacknum;
}
if (root->col == RED && root->_parent && root->_parent->col == RED)
{
cout << root->_kv.first << "出现连续红色节点" << endl;
return false;
}
return CheckColor(root->_left, blacknum, benchmark)
&& CheckColor(root->_right, blacknum, benchmark);
}
bool IsRBTree()
{
return _IsRBTree(_root);
}
bool _IsRBTree(Node* root)
{
if (root == nullptr)
return true;
if (root->col == RED)
{
return false;
}
//基准值
int benchmark = 0;
Node* cur = _root;
while (cur)
{
if (cur->col == BLACK)
++benchmark;
cur = cur->_left;
}
return CheckColor(root, 0, benchmark);
}
private:
Node* _root = nullptr;
};
一、红黑树的完善:
1、红黑树节点模版的修改:
这里要将红黑树节点的模版从两个修改为一个T,这是首先通过set或者map的模版参数传给红黑树的第二个模版参数进行实例化Node。
2、仿函数在模拟实现中的应用:
再节点中存储的是T的,在set中这个T是K结构的,在进行比较的时候,直接访问比较就可以了,但是在map中这个T是K,V结构的键值对,在进行比较的时候,就不能够直接比较,这个时候就可以通过仿函数(通过对一个类进行()的重载,使这个类在使用的时候看上去像一个函数)取这个键值对中的first来进行比较即可。
所以在传模版的时候就需要第三个模版参数来进行仿函数的控制。
map中的仿函数实现:
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<const K, V>, MapKeyOfT> _t;
};
set中的仿函数的实现:
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
private:
RBTree<K, K, SetKeyOfT> _t;
};
仿函数在比较中的应用:
上面是部分代码的修改:
下面是仿函数在红黑树中的使用思路:
如上所示:
通过在自我实现的map或者是set中进行仿函数的实现,在set中返回key值即可,在map中返回这个键对值的first即可。
这样在比较的时候就可以实现map的大小比较了。
3、新增迭代器:
将红黑树的节点进行再一次的封装,这样封装出一个迭代器的类,应该是只有一个模版参数T但是要实现const迭代器和普通迭代器要使用这个迭代器的类,这样再加上两个模版参数来进行迭代器的实现。
template<class T, class Ptr, class Ref>
struct __TreeIterator
{
typedef RBTreeNode<T> Node;
typedef __TreeIterator<T, Ptr, Ref> Self;
Node* _node;
};
构造函数:
__TreeIterator(Node* node)
:_node(node)
{}
解引用操作:
Ref operator*()
{
return _node->_data;
}
->操作:
Ptr operator->()
{
return &_node->_data;
}
!=操作
bool operator!=(const Self& s) const
{
return _node != s._node;
}
++操作
思路:
首先进行此判断,当前迭代器所指向的位置进行++操作后,要么在右子树的最小节点或者是往祖先找,下一个节点要是一个父节点的左节点。
那么就进行判断:
如果此时迭代器所指向的节点右边存在子树,那么就直接找到右子树的最左节点给node最后进行返回*this.
如果此时迭代器所指向的节点右边不存在子树,那么就往祖先找,直到找到孩子是父节点左的那个节点,就是下一个要访问的节点。
Self& operator++()
{
if (_node->_right)
{
//右子树不是空,就找右子树的最小节点(最左边的节点)
Node* RightTree = _node->_right;
while (RightTree->_left)
{
RightTree = RightTree->_left;
}
_node = RightTree;
}
else
{
//右为空,就找孩子是父节点的左孩子的那个父节点
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
--操作:
思路:
首先进行此判断,当前迭代器所指向的位置进行--操作后,要么在左子树的最大节点或者是往祖先找,下一个节点要是一个父节点的右节点。
如果迭代器所指向的节点的左子树不为空,则--操作后应该找到其左子树当中的最右结点。
如果迭代器所指向的节点的左子树为空,则--操作后应该在该结点的祖先结点中,找到孩子不在父亲左的祖先。那么就进行判断:
如果此时迭代器所指向的节点左边存在子树,那么就直接找到左子树的最右节点给node最后进行返回*this.
如果此时迭代器所指向的节点左边不存在子树,那么就往祖先找,直到找到孩子是父节点右的那个节点,就是下一个要访问的节点。
Self& operator--()
{
if (_node->_left)
{
Node* RootRight = _node->_left;
while (RootRight->_right)
{
RootRight = RootRight->_right;
}
_node = RootRight;
}
else
{
//要找到孩子是父亲的右边的那个节点就是--后的值
Node* cur = _node;
Node* parent = _node->_parent;
while (parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
4、红黑树中的迭代器实现:
既然有了迭代器这个类,那么在红黑树中就可以进行begin和end的实现:
template<class K, class T, class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef __TreeIterator<T, T*, T&> iterator;
typedef __TreeIterator<T, const T*, const T&> const_iterator;
iterator begin()
{
Node* leftmin = _root;
while (leftmin && leftmin->_left)
{
leftmin = leftmin->_left;
}
return iterator(leftmin);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin() const
{
Node* leftmin = _root;
while (leftmin && leftmin->_left)
{
leftmin = leftmin->_left;
}
return const_iterator(leftmin);
}
const_iterator end() const
{
return const_iterator(nullptr);
}
};
二、set与map的模拟实现:
在下面我们需要修改insert的实现,接着通过insert来进行map中的[ ]的实现。
1、insert:
首先将insert的返回值修改为iterator和bool的键对值,接着将实现中的return都修改一下:
在修改RBTree中的insert之后,也要对map和set中的insert进行修改:
map中:
直接进行调用即可
set中:
不能够直接进行调用,因为存在迭代器不匹配的问题,那么看看STL标准模板库中的解决方式:
上述是在set中的标准库中的实现,先直接抄过来看看:
可以知道,将set的insert实现的代码从直接调用变成上述中就可以编译通过,解决方法:
那么就需要在迭代器类中增加一个构造函数
当这个类被实例化成const迭代器的时候,这就是一个普通构造,是普通迭代器构造const迭代器,但是如果这个类被实例化成普通迭代器的时候,新增的就是一个拷贝构造(普通迭代器构造普通迭代器)
2、map的[ ]:
三、测试:
int main()
{
ppr::map<int, int> m;
m.Insert(make_pair(1, 1));
m.Insert(make_pair(3, 3));
m.Insert(make_pair(2, 2));
ppr::map<int, int>::iterator mit = m.begin();
while (mit != m.end())
{
// 不能修改key,可以修改value
//mit->first = 1;
mit->second = 2;
cout << mit->first << ":" << mit->second << endl;
++mit;
}
cout << endl;
ppr::set<int> s;
s.Insert(5);
s.Insert(2);
s.Insert(2);
s.Insert(12);
s.Insert(22);
s.Insert(332);
s.Insert(7);
ppr::set<int>::iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
for (const auto& e : s)
{
cout << e << " ";
}
cout << endl;
ppr::map<string, string> dict;
dict.Insert(make_pair("sort", "111"));
dict["apple"]; // 插入
for (const auto& kv : dict)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
dict["apple"] = "苹果"; // 修改
dict["sort"] = "222"; // 修改
dict["pear"] = "梨"; // 插入+修改
for (const auto& kv : dict)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
return 0;
}
四、完整代码:
红黑树:
#pragma once
#include<iostream>
using namespace std;
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)
, col(RED)
{}
};
template<class T, class Ptr, class Ref>
struct __TreeIterator
{
typedef RBTreeNode<T> Node;
typedef __TreeIterator<T, Ptr, Ref> Self;
typedef __TreeIterator<T, T*, T&> iterator;
__TreeIterator(const iterator& it)
:_node(it._node)
{}
Node* _node;
__TreeIterator(Node* node)
:_node(node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
bool operator!=(const Self& s) const
{
return _node != s._node;
}
Self& operator--()
{
if (_node->_left)
{
Node* RootRight = _node->_left;
while (RootRight->_right)
{
RootRight = RootRight->_right;
}
_node = RootRight;
}
else
{
//要找到孩子是父亲的右边的那个节点就是--后的值
Node* cur = _node;
Node* parent = _node->_parent;
while (parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self& operator++()
{
if (_node->_right)
{
//右子树不是空,就找右子树的最小节点(最左边的节点)
Node* RightTree = _node->_right;
while (RightTree->_left)
{
RightTree = RightTree->_left;
}
_node = RightTree;
}
else
{
//右为空,就找孩子是父节点的左孩子的那个父节点
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
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 __TreeIterator<T, T*, T&> iterator;
typedef __TreeIterator<T, const T*, const T&> const_iterator;
iterator begin()
{
Node* leftmin = _root;
while (leftmin && leftmin->_left)
{
leftmin = leftmin->_left;
}
return iterator(leftmin);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin() const
{
Node* leftmin = _root;
while (leftmin && leftmin->_left)
{
leftmin = leftmin->_left;
}
return const_iterator(leftmin);
}
const_iterator end() const
{
return const_iterator(nullptr);
}
Node* Find(const K& key)
{
Node* cur = _root;
KeyOfT kot;
while (cur)
{
if (kot(cur->_data) < key)
{
cur = cur->_right;
}
else if (kot(cur->_data) > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return nullptr;
}
pair<iterator, bool> Insert(const T& data)
{
//先进来判断这个树是不是空树
if (_root == nullptr)
{
_root = new Node(data);
_root->col = BLACK;
return make_pair(iterator(_root), true);
}
Node* parent = nullptr;
Node* cur = _root;
Node* newnode = cur;
//找到要插入的位置
KeyOfT kot;
while (cur)
{
if (kot(cur->_data) > kot(data))
{
parent = cur;
cur = cur->_left;
}
else if (kot(cur->_data) < kot(data))
{
parent = cur;
cur = cur->_right;
}
else
{
return make_pair(iterator(cur), false);
}
}
//走到这就是找到了
cur = new Node(data);
cur->col = RED;
//再连接到这个红黑树中
if (kot(parent->_data) > kot(cur->_data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
//已经连接完成后
while (parent && parent->col == RED)
{
//这里祖父必定存在,因为如果进循环后parent就是red,然而red不可能为根节点,所以parent的parent必定存在
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
if (uncle && uncle->col == RED)
{
//修改颜色
uncle->col = BLACK;
parent->col = BLACK;
grandfather->col = RED;
//修改cur
cur = grandfather;
//修改parent继续指向cur的parent
parent = cur->_parent;
}
else//uncle不存在或者uncle为黑色就需要旋转了
{
if (cur == parent->_left)
{
RotateR(grandfather);
parent->col = BLACK;
grandfather->col = RED;
}
else//cur == parent->_right
{
RotateL(parent);
RotateR(grandfather);
cur->col = BLACK;
grandfather->col = RED;
}
break;
}
}
else//parent == grandfather->_right
{
Node* uncle = grandfather->_left;
if (uncle && uncle->col == RED)
{
//修改颜色
uncle->col = BLACK;
parent->col = BLACK;
grandfather->col = RED;
//修改cur
cur = grandfather;
//修改parent继续指向cur的parent
parent = cur->_parent;
}
else//uncle不存在或者uncle为黑色就需要旋转了
{
if (cur == parent->_right)
{
RotateL(grandfather);
parent->col = BLACK;
grandfather->col = RED;
}
else//cur == parent->_right
{
RotateR(parent);
RotateL(grandfather);
cur->col = BLACK;
grandfather->col = RED;
}
break;
}
}
}
_root->col = BLACK;
return make_pair(iterator(newnode), true);
}
//左单旋
void RotateL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
parent->_right = curleft;
if (curleft)
{
curleft->_parent = parent;
}
cur->_left = parent;
//将parent的父节点保存起来
Node* pparent = parent->_parent;
parent->_parent = cur;
if (parent == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (pparent->_left == parent)
{
pparent->_left = cur;
}
else
{
pparent->_right = cur;
}
cur->_parent = pparent;
}
}
//右单旋
void RotateR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
parent->_left = curright;
if (curright)
{
curright->_parent = parent;
}
cur->_right = parent;
//将parent的父节点保存起来
Node* pparent = parent->_parent;
parent->_parent = cur;
if (parent == _root)
{
_root = cur;
cur->_parent = nullptr;
}
else
{
if (pparent->_left == parent)
{
pparent->_left = cur;
}
else
{
pparent->_right = cur;
}
cur->_parent = pparent;
}
}
bool CheckColor(Node* root, int blacknum, int benchmark)
{
if (root == nullptr)
{
if (blacknum != benchmark)
{
cout << "黑色节点的数量不匹配" << endl;
return false;
}
return true;
}
if (root->col == BLACK)
{
++blacknum;
}
if (root->col == RED && root->_parent && root->_parent->col == RED)
{
cout << root->_kv.first << "出现连续红色节点" << endl;
return false;
}
return CheckColor(root->_left, blacknum, benchmark)
&& CheckColor(root->_right, blacknum, benchmark);
}
bool IsRBTree()
{
return _IsRBTree(_root);
}
bool _IsRBTree(Node* root)
{
if (root == nullptr)
return true;
if (root->col == RED)
{
return false;
}
//基准值
int benchmark = 0;
Node* cur = _root;
while (cur)
{
if (cur->col == BLACK)
++benchmark;
cur = cur->_left;
}
return CheckColor(root, 0, benchmark);
}
private:
Node* _root = nullptr;
};
模拟实现map:
#pragma once
#include"RBTree.h"
namespace ppr
{
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<const K, V>, MapKeyOfT>::iterator iterator;
typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::const_iterator 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();
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = Insert(make_pair(key, V()));
return ret.first->second;
}
pair<iterator, bool> Insert(const pair<K, V>& kv)
{
return _t.Insert(kv);
}
private:
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
}
模拟实现set:
#pragma once
#include"RBTree.h"
namespace ppr
{
template<class K>
class set
{
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator iterator;
typedef typename RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;
iterator begin() const
{
return _t.begin();
}
iterator end() const
{
return _t.end();
}
pair<iterator, bool> Insert(const K& kv)
{
//类模版里面取内置类型要加上typename告诉编译器这是一个类型
pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(kv);
return pair<iterator, bool>(ret.first, ret.second);
}
private:
RBTree<K, K, SetKeyOfT> _t;
};
}