目录
一.set与map在STL中的源码
想要简单实现set与map 需要我们稍微理解其底层代码。以下是简化部分
set:
template <class Key, class Compare = less<Key>, class Alloc = alloc>
class set {
public:
// typedefs:
typedef Key key_type;
typedef Key value_type;
typedef Compare key_compare;
typedef Compare value_compare;
private:
typedef rb_tree<key_type, value_type,
identity<value_type>, key_compare, Alloc> rep_type;
rep_type t; // red-black tree representing set
//·····
}
map:
template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
class map {
public:
// typedefs:
typedef Key key_type;
typedef T data_type;
typedef T mapped_type;
typedef pair<const Key, T> value_type;
typedef Compare key_compare;
//·····
private:
typedef rb_tree<key_type, value_type,
select1st<value_type>, key_compare, Alloc> rep_type;
rep_type t; // red-black tree representing map
//·····
}
从两者私有部分不难看出,两者的底层都使用了红黑树。但一棵红黑树只能为K-V模型或K模型,那是如何同时满足map的K-V模型和set的K模型的呢?
不难看出,set与map虽然共用了一颗红黑树,但传入值的方式不一样
set传入的为<K,K>, map传入的是<K, pair<const K, V> >
关于两类模板参数,第一个K方便find和erase接口,第二个则决定我们的红黑树是那种模型,那怎样将两种模型泛化到一起呢?
由于用户只能从上层调用接口,我们在底层添加模板参数T,set对于T传入K,map对于T传入
pari<const K, V>。具体如下
set:
template<class K>
class set
{
public:
private:
RBTree<K, const K, SetKeyOfT> _t;
};
map:
template<class K, class V>
class map
{
public:
private:
// key不能修改(第一个k为什么不加const?
//第一个K 只用于删除和查找, 外层修改不到。
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
RBTree:
enum Colour
{
RED, //0
BLACK //1
};
//RBTree树节点
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
Colour _col;
RBTreeNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
, _col(RED)
{ }
};
template<class K, class T>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
private:
Node* _root = nullptr;
};
二.修改红黑树
1.插入与查找时的比较方式
当我们插入元素时,set插入的元素为K,比较大小时可以直接比较,map插入的元素为pair<K,V>,在C++中pair直接比较则会首先按照first的大小比较,first相同时再按照second大小比较,这显然不是我们期望的只用K关键字比较。那么如何才能使用一种统一的方式解决这个问题呢?
采用仿函数
在map和set类中添加各自的仿函数,其功能是拿到各自的Key,便于红黑树的比较。
set:
template<class K>
class set
{
//仿函数 因为map中红黑树的T 为pair, set中为K, 为了泛型编程
//我们使用仿函数对map和set进行统一处理
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
private:
RBTree<K, const K, SetKeyOfT> _t;
};
map:
template<class K, class V>
class map
{
//仿函数 因为map中红黑树的T 为pair, set中为K, 为了泛型编程
//我们使用仿函数对map和set进行统一处理
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
public:
private:
// key不能修改(第一个k为什么不加const?
//第一个K 只用于删除和查找, 外层修改不到。
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
RBTree:模板中添加仿函数
enum Colour
{
RED, //0
BLACK //1
};
//RBTree树节点
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
Colour _col;
RBTreeNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
, _col(RED)
{ }
};
template<class K, class T,class KeyOfT>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
private:
Node* _root = nullptr;
};
2.插入时的返回值
在C++源码中, set与map插入的返回值都是pair类型:其意为如果插入成功与否,都返回一个pair类型,如果成功则返回插入位置的迭代器与true,如果失败则返回重复元素位置的迭代器与false。所以,我们应修改Insert函数的返回值。
完善后的Insert函数(内含的迭代器部分在下面会讲,先关注返回值与比较部分即可):
//插入成功--->返回插入位置和true
//插入失败--->返回该元素存在的位置和false
pair<Iterator, bool> Insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(Iterator(_root), true);
}
KeyOfT kot;
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
// K
// pair<K, V>
// kot对象,是用来取T类型的data对象中的key
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);
cur->_col = RED;
//记录cur位置
Node* newnode = cur;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
// 别忘记指向父亲
cur->_parent = parent;
// 往上更新 如果父亲的颜色是黑色就停止
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;
parent = cur->_parent;
}
// 叔叔不存在或者存在且为黑
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);
//cur去了g的位置 g去了u的位置
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 // 叔叔不存在,或者存在且为黑
{
// g
// u p
// c
if (cur == parent->_right)
{
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// g
// u p
// c
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
// 如果根节点变红了 设回黑
_root->_col = BLACK;
return make_pair(Iterator(newnode), true);
}
3.补充成员函数
在简单实现中,我们需要把必要的默认成员函数补上。
//我们手写了默认成员函数后 编译器不在为我们自动生成
// + default 要编译器给我们生成默认构造 运行效率更好
RBTree() = default;
//拷贝
RBTree(const RBTree<K, T, KeyOfT>& t)
{
//深拷贝
_root = _Copy(t._root);
}
//赋值 重载运算符
RBTree<K, T, KeyOfT>& operator=(const RBTree<K, T, KeyOfT> t)
{
//t是形参 相当于和副本交换了
swap(_root, t._root);
return *this;
}
~RBTree()
{
_Distory(_root);
_root = nullptr;
}
private:
//递归式删除
void _Distory(Node* root)
{
if (root == nullptr)
return;
_Distory(root->_left);
_Distory(root->_right);
delete root;
root = nullptr;
}
Node* _Copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* newroot = new Node(root->_data);
newroot->_col = root->_col;
newroot->_left = _Copy(root->_left);
if (newroot->_left)
newroot->_left->_parent = newroot;
newroot->_right = _Copy(root->_right);
if (newroot->_right)
newroot->_right->_parent = newroot;
return newroot;
}
三.封装set与map
1.迭代器的实现
对于迭代器,我们要实现begin()、end()、*iterator、iterator->、++iterator、!=这四种常见功能。另外,我们希望从外部访问迭代器,只访问到树节点的数据:set只访问K,map只访问pair<const K, V>,因为用户访问树节点的左右父亲颜色等没有意义。
初始化:用一个树的节点来初始化
begin()与end():
对于一棵红黑树,其中序遍历时有序的,也就是说我们在用迭代器从begin()访问到end()的过程中也是有序的。基于此,迭代器的begin()指向的位置应当是整棵树中最小的数即最左的节点(图中改为1)。end()作为最大节点的后一个元素,为空即可。
*iterator:对迭代器解引用,应返回对数据的引用
iterator->:引出迭代器的元素,应返回对应数据的地址(编译器会帮我们优化)
++iterator:对于前置++操作,在上图中访问顺序为1-6-8-11-13-15-17-22-25-27
规律为:若一个节点有右子树,则访问其右子树的最左节点;若没有右子树,则倒着往上寻找一个孩子为父亲左的一个祖先。
!=:直接比较两个值相不相等即可。
在树外新建一个类进行实现,当然也可以嵌在树中当内部类。
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;
}
//前置++
Self& operator++()
{
//++操作迭代器指向的元素一定是按顺序的
if (_node->_right)
{
//如果有右树, 下一个节点为右数的最左边
Node* leftMin = _node->_right;
while (leftMin->_left)
{
leftMin = leftMin->_left;
}
_node = leftMin;
}
else
{
//没有右树,倒着在祖先里找,找孩子是父亲左的祖先
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = parent;
parent = cur->_parent;
}
_node = parent;
}
return *this;
}
};
Iterator Begin()
{
//空不空无所谓
Node* leftMin = _root;
while (leftMin && leftMin->_left)
{
leftMin = leftMin->_left;
}
return Iterator(leftMin);
}
Iterator End()
{
return Iterator(nullptr);
}
2.函数接口
在我们map与set里面对迭代器的接口封装以下即可。
set:
template<class K>
class set
{
//仿函数 因为map中红黑树的T 为pair, set中为K, 为了泛型编程
//我们使用仿函数对map和set进行统一处理
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
//消除二义性 让编译器知道你要给一个类型取别名 而不是 定义一个变量
typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
private:
RBTree<K, const K, SetKeyOfT> _t;
};
map:
template<class K, class V>
class map
{
//仿函数 因为map中红黑树的T 为pair, set中为K, 为了泛型编程
//我们使用仿函数对map和set进行统一处理
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;
iterator begin()
{
return _t.Begin();
}
iterator end()
{
return _t.End();
}
private:
// key不能修改(第一个k为什么不加const?
//第一个K 只用于删除和查找, 外层修改不到。
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
3.map中的operator[]
对于map,其支持方括号下标访问。
形如:
map<string, int> mp;
mp[”x”] = 1;
其原理为若有”x“,则修改其对应值为1,若无“x”,则插入”x“,值为1。
所以重载[]时应进行插入,用pair类型接收。
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.Insert({key,V()});
//map迭代器是一个节点的指针 "->"我们重载过 得到pair类型 pair<const K, V> 返回second;
return ret.first->second;
}
四.完整代码
最后补充const迭代器以及一些细节,代码里有注释。附测试。
set.h
#pragma once
//template <class Key, class Compare = less<Key>, class Alloc = alloc>
//class set {
//public:
// typedef Key key_type;
// typedef Key value_type;
//private:
// typedef rb_tree<key_type, value_type,
// identity<value_type>, key_compare, Alloc> rep_type;
// rep_type t; // red-black tree representing set
//}
// 抓重点
// 化繁为简,只关注跟抓重点部分有关系的,其他通通不关注
namespace Xiang
{
template<class K>
class set
{
//仿函数 因为map中红黑树的T 为pair, set中为K, 为了泛型编程
//我们使用仿函数对map和set进行统一处理
struct SetKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
//消除二义性 让编译器知道你要给一个类型取别名 而不是 定义一个变量
typedef typename RBTree<K, const K, SetKeyOfT>::Iterator iterator;
typedef typename RBTree<K, const K, SetKeyOfT>::ConstIterator 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 K& key)
{
return _t.Insert(key);
}
iterator find(const K& key)
{
return _t.Find(key);
}
private:
RBTree<K, const K, SetKeyOfT> _t;
};
void PrintSet(const set<int>& s)
{
for (auto e : s)
{
cout << e << endl;
}
}
void test_set()
{
set<int> s;
s.insert(4);
s.insert(2);
s.insert(5);
s.insert(15);
s.insert(7);
s.insert(1);
s.insert(5);
s.insert(7);
PrintSet(s);
set<int>::iterator it = s.begin();
while (it != s.end())
{
//*it += 5;
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
set<int> copy = s;
for (auto e : copy)
{
cout << e << " ";
}
cout << endl;
//cout << copy._t.IsBalance() << endl;
}
}
map.h
#pragma once
//template <class Key, class T, class Compare = less<Key>, class Alloc = alloc>
//class map {
//public:
// typedef Key key_type;
// typedef pair<const Key, T> value_type;
//
//private:
// typedef rb_tree<key_type, value_type,
// select1st<value_type>, key_compare, Alloc> rep_type;
// rep_type t; // red-black tree representing map
//};
namespace Xiang
{
template<class K, class V>
class map
{
//仿函数 因为map中红黑树的T 为pair, set中为K, 为了泛型编程
//我们使用仿函数对map和set进行统一处理
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>::ConstIterator 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);
}
//find 返回迭代器
iterator find(const K& key)
{
return _t.Find(key);
}
V& operator[](const K& key)
{
pair<iterator, bool> ret = _t.Insert({key,V()});
//map迭代器是一个节点的指针 "->"我们重载过 得到pair类型 pair<const K, V> 返回second;
return ret.first->second;
}
private:
// key不能修改(第一个k为什么不加const?
//第一个K 只用于删除和查找, 外层修改不到。
RBTree<K, pair<const K, V>, MapKeyOfT> _t;
};
void test_map1()
{
map<string, int> m;
m.insert({ "乐",1 });
m.insert({ "通",1 });
m.insert({ "给",1 });
m.insert({ "哦",3 });
cout << m["乐"] << endl << "有乐" << endl;
map<string, int>::iterator it = m.begin();
while (it != m.end())
{
//it->first += 'x';
it->second += 1;
//cout << it.operator->()->first << ":" << it->second << endl;
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
}
void test_map2()
{
string arr[] = { "a", "", "a", "", "d", "c", "","他怕", "李", "好", "哦","给","888", "达瓦","h" };
map<string, int> countMap;
for (auto& e : arr)
{
countMap[e]++;
}
for (auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
}
RBTree.h
#pragma once
enum Colour
{
RED, //0
BLACK //1
};
//RBTree树节点
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
Colour _col;
RBTreeNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
// 新插入节点默认红的
//因为插入红节点可能违反规则三,但插入黑节点一定违反规则四
, _col(RED)
{ }
};
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;
}
//前置++
Self& operator++()
{
//++操作迭代器指向的元素一定是按顺序的
if (_node->_right)
{
//如果有右树, 下一个节点为右数的最左边
Node* leftMin = _node->_right;
while (leftMin->_left)
{
leftMin = leftMin->_left;
}
_node = leftMin;
}
else
{
//没有右树,倒着在祖先里找,找孩子是父亲左的祖先
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = parent;
parent = cur->_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;
typedef __RBTreeIterator<T, const T&, const T*> ConstIterator;
//我们手写了默认成员函数后 编译器不在为我们自动生成
// + default 要编译器给我们生成默认构造 运行效率更好
RBTree() = default;
//拷贝
RBTree(const RBTree<K, T, KeyOfT>& t)
{
//深拷贝
_root = _Copy(t._root);
}
//赋值 重载运算符
RBTree<K, T, KeyOfT>& operator=(const RBTree<K, T, KeyOfT> t)
{
//t是形参 相当于和副本交换了
swap(_root, t._root);
return *this;
}
~RBTree()
{
_Distory(_root);
_root = nullptr;
}
//begin 为最左节点 end为空节点
Iterator Begin()
{
//空不空无所谓
Node* leftMin = _root;
while (leftMin && leftMin->_left)
{
leftMin = leftMin->_left;
}
return Iterator(leftMin);
}
ConstIterator Begin() const
{
Node* leftMin = _root;
while (leftMin && leftMin->_left)
{
leftMin = leftMin->_left;
}
return ConstIterator(leftMin);
}
Iterator End()
{
return Iterator(nullptr);
}
ConstIterator End() const
{
return ConstIterator(nullptr);
}
Iterator Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (KeyOfT(cur->_data) < key)
{
cur = cur->_right;
}
else if (KeyOfT(cur->_data) > key)
{
cur = cur->_left;
}
else
{
return Iterator(cur);
}
}
return End();
}
//插入成功--->返回插入位置和true
//插入失败--->返回该元素存在的位置和false
pair<Iterator, bool> Insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(Iterator(_root), true);
}
KeyOfT kot;
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
// K
// pair<K, V>
// kot对象,是用来取T类型的data对象中的key
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);
cur->_col = RED;
//记录cur位置
Node* newnode = cur;
if (kot(parent->_data) < kot(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
// 别忘记指向父亲
cur->_parent = parent;
// 往上更新 如果父亲的颜色是黑色就停止
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;
parent = cur->_parent;
}
// 叔叔不存在或者存在且为黑
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);
//cur去了g的位置 g去了u的位置
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 // 叔叔不存在,或者存在且为黑
{
// g
// u p
// c
if (cur == parent->_right)
{
RotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// g
// u p
// c
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
// 如果根节点变红了 设回黑
_root->_col = BLACK;
return make_pair(Iterator(newnode), true);
}
//右旋
void RotateR(Node* parent)
{
// 要更改六条边
Node* subL = parent->_left;
Node* subLR = subL->_right;
// 先处理parent和SubLR
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
//再处理parent和 subl
//因为 后面需要把 parent的parent和subl链接
//需要先保存parent的parent
subL->_right = parent;
Node* ppNode = parent->_parent;
parent->_parent = subL;
//处理 subl的 父节点
if (parent == _root)
{
_root = subL;
_root->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subL;
}
else
{
ppNode->_right = subL;
}
subL->_parent = ppNode;
}
}
//左旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL)
subRL->_parent = parent;
subR->_left = parent;
Node* ppNode = parent->_parent;
parent->_parent = subR;
if (parent == _root)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if (ppNode->_left == parent)
{
ppNode->_left = subR;
}
else
{
ppNode->_right = subR;
}
subR->_parent = ppNode;
}
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool IsBalance()
{
if (_root->_col == RED)
{
return false;
}
int refNum = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
++refNum;
}
cur = cur->_left;
}
return _Check(_root, 0, refNum);
}
int Height()
{
return _Height(_root);
}
int Size()
{
return _Size(_root);
}
private:
//递归式删除
void _Distory(Node* root)
{
if (root == nullptr)
return;
_Distory(root->_left);
_Distory(root->_right);
delete root;
root = nullptr;
}
Node* _Copy(Node* root)
{
if (root == nullptr)
return nullptr;
Node* newroot = new Node(root->_data);
newroot->_col = root->_col;
newroot->_left = _Copy(root->_left);
if (newroot->_left)
newroot->_left->_parent = newroot;
newroot->_right = _Copy(root->_right);
if (newroot->_right)
newroot->_right->_parent = newroot;
return newroot;
}
int _Size(Node* root)
{
return root == nullptr ? 0 : _Size(root->_left) + _Size(root->_right) + 1;
}
int _Height(Node* root)
{
if (root == nullptr)
return 0;
return max(_Height(root->_left), _Height(root->_right)) + 1;
}
bool _Check(Node* root, int blackNum, const int refNum)
{
if (root == nullptr)
{
//cout << blackNum << endl;
if (refNum != blackNum)
{
cout << "存在黑色节点的数量不相等的路径" << endl;
return false;
}
return true;
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << root->_kv.first << "存在连续的红色节点" << endl;
return false;
}
if (root->_col == BLACK)
{
blackNum++;
}
return _Check(root->_left, blackNum, refNum)
&& _Check(root->_right, blackNum, refNum);
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
cout << root->_kv.first << ":" << root->_kv.second << endl;
_InOrder(root->_right);
}
private:
Node* _root = nullptr;
};