这篇博客完全是根据上篇博客红黑树来扩展的,代码的修改也是在红黑树那篇,大家可以先看看那篇代码再过来看看这篇更好食用哦!
1.红黑树迭代器代码
2.红黑树的insert代码
3.map和set的封装
4.最后代码总和
5.最终测试
模板参数只需要一个即可,
enum Colour
{
RED,
BLACK
};
template
struct RBTreeNode
{
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
T _date;//数据
Colour _col;
RBTreeNode(const T& date)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _date(date)
, _col(RED)
{}
};
(1) operator* : 用来取出结点的数据,返回值&即可.
(2) operator-> :用来返回结点的地址, 用于map里访问pair里面的first 和 second.
(3) operator++ :
迭代器++, 因为是二叉树的遍历++; 那么有下面两种情况; 请看图哦!
可以发现(1)node结点的右子树是否为空; 如果不为空就是遍历到右子树的最左边结点;
(2)如果为空的话; 那么就说明这层子树以及遍历完了,我们需要回到祖父(parent的parent)去找另外一层子树的结点.
(4) operator-- :同样我们上图片看的更加明白;
可以发现: (1) node结点的左边结点是否存在,如果存在;那么就结点遍历到左子树的最右结点;
(2)如果node结点不存在的话,由于红黑树是二叉树,左子树不存在那么右子树更加不存在;
就代表这层树最左结点遍历完了,我们需要找到祖父结点去找.
(5)operator!= / operator== : 直接看一下代码就很快了解啦.
template
struct __TreeIterator
{
typedef RBTreeNode Node;
typedef __TreeIterator Self;
Node* _node;
__TreeIterator(Node* node)
:_node(node)
{}
T& operator*()//解引用,取数据date的引用
{
return _node->_date;
}
T* operator->()//取数据date的地址,在解引用得到数据传回去.
{
return &_node->_date;
}
Self& operator--()//迭代器--
{
if (_node->_left)
{
Node* cur = _node->_left;
while (cur->_right)
{
cur = cur->_right;
}
_node = cur;
}
else//左结点不存在的话那右结点也不会存在那么就要找祖父结点.
{
Node* parent = _node->_parent;
Node* cur = _node;
while (parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = cur;
}
return *this;
}
Self& operator--(int)//后置--
{
Self it(_node);
--(*this);
return it;
}
Self& operator++()//迭代器++
{
if (_node->_right)//结点的右子树存在,那么下一个结点一定是右子树的最左结点.
{
Node* cur = _node->_right;
while (cur->_left)
{
cur = cur->_left;
}
_node = cur;
}
else//结点的右子树不存在,那么这颗树走完了,需要到孩子是父亲左的祖先.
{
Node* cur = _node;
while (parent && cur == parent->_right)
{
cur = parent;
parent = cur->_parent;
}
_node = cur;
}
return *this;
}
Self& operator++(int)//后置++
{
Self it(_node);
++(*this);
return it;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator==(const Self& s)
{
return _node == s._node;
}
};
(1) begin是红黑树的最左边结点;
(2) end是由于结构要求就是设置为nullptr;
(3)const_iterator也是一样就是多了const,无法修改.
public:
typedef __TreeIterator iterator;
typedef __TreeIterator const_iterator;
iterator begin()
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return iterator(cur);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin()const
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return iterator(cur);
}
const_iterator end()const
{
return iterator(nullptr);
}
(1)返回值是pair
, 返回迭代器和布尔参数.(2)因为set和map是一起处理的, 那么传入数据模板统一都是T;
(3)KeyOfT是用来获取set和map中的key来进行比较的; 因为class是无法拿数据直接比较的.
如果插入相同的那么就是失败返回make_pair(iterator(cur), false).
(4)参数类型是const T& date.
pair Insert(const T& date)
{
if (_root == nullptr)//结点为空
{
_root = new Node(date);
_root->_col = BLACK;
return make_pair(iterator(_root), true);
}
Node* parent = nullptr;
Node* cur = _root;
KeyOfT kot; //set和map数据kay的比较
while (cur)//固定cur的位置
{
if (kot(cur->_date) < kot(date))//右边
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_date) > kot(date))//左边
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur), false);
}
}
cur = new Node(date);
Node* newnode = cur;
cur->_col = RED;
if (kot(parent->_date) < kot(date)//右边
{
parent->_right = cur;
cur->_parent = parent;
}
else//左边
{
parent->_left = cur;
cur->_parent = parent;
}
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
// g
// p u
//c
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
// c
RotateR(grandfather);//直接右单旋
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// g
// p
// c
RotateL(parent);//先左单旋parent
RotateR(grandfather);//在旋转grandfather
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else//父亲结点在祖父结点的右边;
{
// g
// u p
// c
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
//继续去上面结点处理
cur = grandfather;
parent = cur->_parent;
}
else//u结点是空或者黑色结点.
{
// 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 RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
subR->_left = parent;
Node* parentParent = parent->_parent;
parent->_parent = subR;
if (subRL)
subRL->_parent = parent;
if (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (parentParent->_left == parent)
{
parentParent->_left = subR;
}
else
{
parentParent->_right = subR;
}
subR->_parent = parentParent;
}
}
void RotateR(Node* parent)//对于第二种情况下左单旋和右单旋;
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* parentParent = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (parentParent->_left == parent)
{
parentParent->_left = subL;
}
else
{
parentParent->_right = subL;
}
subL->_parent = parentParent;
}
}
使用Height为了外面使用时候不用传递参数直接调用 _Height.
采用dfs递归的方法,遍历二叉搜索树.
int Height()
{
return _Height(_root);
}
int _Height(Node* root)
{
if (root == nullptr)
return 0;
int leftHeight = _Height(_root->_left);
int rightHeight = _Height(_root->_right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
也是采用递归方法,遍历二叉搜索树的左右结点.
size_t Size()
{
return _Size(_root);
}
size_t _Size(Node* root)
{
if (root == nullptr)
return 0;
return _Size(root->_left)
+ _Size(root->_right) + 1;
}
就是和找到插入数据结点的位置是一个逻辑.
Node* find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < key)
{
cur = cur->_right;
}
else if (cur->_kv.first > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return NULL;
}
这部分上篇红黑树详解博客以及写的很清楚了,可以看看那篇.是一样的!
void Inorder()
{
_Inorder(_root);
cout << endl;
}
void _Inorder(Node* root)
{
if (root == nullptr)
return;
_Inorder(root->_left);
cout << root->_kv.first << " ";
_Inorder(root->_right);
}
bool check(Node* root, int blacknum, const int refVal)
{
if (root == nullptr)
{
if (blacknum != refVal)
{
cout << "存在黑色结点不相等的路径" << endl;
return false;
}
return true;
}
//判断一黑一红
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "有连续的红色结点" << endl;
return false;
}
if (root->_col == BLACK)
{
blacknum++;
}
return check(root->_left, blacknum, refVal) && check(root->_right, blacknum, refVal);
}
bool IsBalance()
{
if (_root == nullptr)
return true;
//检查根结点
if (_root->_col == RED)
return false;
//参考值
int refVal = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
refVal++;
}
cur = cur->_left;
}
//检查一黑一红//检查黑色结点数量
int blacknum = 0;
return check(_root, 0, refVal);
}
(1) SetKeyofT是用来operator(); 因为在比较数据时候得拿出来key那么必须封装起来;直接去取是拿不到的.
namespace study
{
template
class set
{
public:
struct SetKeyofT//在进行比较数据的时候需要用到
{
const K& operator()(const K& key)
{
return key;
}
};
//+typename是因为对模板取内嵌类型需要+typename告诉编译器是类型
typedef RBTree::iterator iterator;
typedef RBTree::const_iterator const_iterator;
iterator begin()const
{
return _t.begin();
}
iterator end()const
{
return _t.end();
}
pair insert(const K& key)
{
return _t.Insert(key);
}
private:
RBTree _t;
};
}
3.2map的封装
(1) MapKeyofT也是和set一样的;
(2) 因为map的参数里面有key和value;所以还是和set有不同; operator()是取出kv的first;
(3) 相比set还有多了一个operator[];
pair
ret = insert(make_pair(key, V())); 这里插入数据make_pair(key, V()); V()是匿名对象.返回值就是pair
.
namespace study
{
template
class map
{
public:
struct MapKeyOfT
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
typedef typename RBTree, MapKeyOfT>::iterator iterator;
typedef typename RBTree, MapKeyOfT>::const_iterator const_iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
V& operator[](const K& key)
{
pair ret = insert(make_pair(key, V()));
return ret.first->second;
}
pair insert(const pair& kv)
{
return _t.Insert(kv);
}
private:
RBTree, MapKeyOfT> _t;
};
}
将代码分成这几个.h / .cpp文件;
#pragma once
#include
using namespace std;
enum Colour
{
RED,
BLACK
};
template
struct RBTreeNode
{
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
T _date;//数据
Colour _col;
RBTreeNode(const T& date)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _date(date)
, _col(RED)
{}
};
template
struct __TreeIterator
{
typedef RBTreeNode Node;
typedef __TreeIterator Self;
Node* _node;
__TreeIterator(Node* node)
:_node(node)
{}
Ref operator*()//解引用,取数据date的引用
{
return _node->_date;
}
Ptr operator->()//取数据date的地址,在解引用得到数据传回去.
{
return &_node->_date;
}
Self& operator--()//迭代器--
{
if (_node->_left)
{
Node* cur = _node->_left;
while (cur->_right)
{
cur = cur->_right;
}
_node = cur;
}
else//左结点不存在的话那右结点也不会存在那么就要找祖父结点.
{
Node* parent = _node->_parent;
Node* cur = _node;
while (parent && cur == parent->_left)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = cur;
}
return *this;
}
Self& operator--(int)//后置--
{
Self it(_node);
--(*this);
return it;
}
Self& operator++()//迭代器++
{
if (_node->_right)//结点的右子树存在,那么下一个结点一定是右子树的最左结点.
{
Node* cur = _node->_right;
while (cur->_left)
{
cur = cur->_left;
}
_node = cur;
}
else//结点的右子树不存在,那么这颗树走完了,需要到孩子是父亲左的祖先.
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
Self& operator++(int)//后置++
{
Self it(_node);
++(*this);
return it;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator==(const Self& s)
{
return _node == s._node;
}
};
template
class RBTree
{
typedef RBTreeNode Node;
public:
typedef __TreeIterator iterator;
typedef __TreeIterator const_iterator;
iterator begin()
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return iterator(cur);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin()const
{
Node* cur = _root;
while (cur && cur->_left)
{
cur = cur->_left;
}
return const_iterator(cur);
}
const_iterator end()const
{
return const_iterator(nullptr);
}
//pair Insert(const T& date)
pair Insert(const T& date)
{
if (_root == nullptr)//结点为空
{
_root = new Node(date);
_root->_col = BLACK;
return make_pair(_root, true);
}
Node* parent = nullptr;
Node* cur = _root;
KeyofT kot; //取出set和map数据key的进行比较;
while (cur)//固定cur的位置
{
if (kot(cur->_date) < kot(date))//右边
{
parent = cur;
cur = cur->_right;
}
else if (kot(cur->_date) > kot(date))//左边
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(cur, false);
}
}
cur = new Node(date);
Node* newnode = cur;
cur->_col = RED;
if (kot(parent->_date) < kot(date))//右边
{
parent->_right = cur;
cur->_parent = parent;
}
else//左边
{
parent->_left = cur;
cur->_parent = parent;
}
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
// g
// p u
//c
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
// c
RotateR(grandfather);//直接右单旋
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// g
// p
// c
RotateL(parent);//先左单旋parent
RotateR(grandfather);//在旋转grandfather
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else//父亲结点在祖父结点的右边;
{
// g
// u p
// c
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
//继续去上面结点处理
cur = grandfather;
parent = cur->_parent;
}
else//u结点是空或者黑色结点.
{
// 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(newnode, true);
}
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
subR->_left = parent;
Node* parentParent = parent->_parent;
parent->_parent = subR;
if (subRL)
subRL->_parent = parent;
if (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (parentParent->_left == parent)
{
parentParent->_left = subR;
}
else
{
parentParent->_right = subR;
}
subR->_parent = parentParent;
}
}
void RotateR(Node* parent)//对于第二种情况下左单旋和右单旋;
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;
Node* parentParent = parent->_parent;
subL->_right = parent;
parent->_parent = subL;
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (parentParent->_left == parent)
{
parentParent->_left = subL;
}
else
{
parentParent->_right = subL;
}
subL->_parent = parentParent;
}
}
void Inorder()
{
_Inorder(_root);
cout << endl;
}
void _Inorder(Node* root)
{
if (root == nullptr)
return;
_Inorder(root->_left);
cout << root->_kv.first << " ";
_Inorder(root->_right);
}
bool check(Node* root, int blacknum, const int refVal)
{
if (root == nullptr)
{
if (blacknum != refVal)
{
cout << "存在黑色结点不相等的路径" << endl;
return false;
}
return true;
}
//判断一黑一红
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "有连续的红色结点" << endl;
return false;
}
if (root->_col == BLACK)
{
blacknum++;
}
return check(root->_left, blacknum, refVal) && check(root->_right, blacknum, refVal);
}
bool IsBalance()
{
if (_root == nullptr)
return true;
//检查根结点
if (_root->_col == RED)
return false;
//参考值
int refVal = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
{
refVal++;
}
cur = cur->_left;
}
//检查一黑一红//检查黑色结点数量
int blacknum = 0;
return check(_root, 0, refVal);
}
int Height()
{
return _Height(_root);
}
int _Height(Node* root)
{
if (root == nullptr)
return 0;
int leftHeight = _Height(_root->_left);
int rightHeight = _Height(_root->_right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
size_t Size()
{
return _Size(_root);
}
size_t _Size(Node* root)
{
if (root == nullptr)
return 0;
return _Size(root->_left)
+ _Size(root->_right) + 1;
}
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_kv.first < key)
{
cur = cur->_right;
}
else if (cur->_kv.first > key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return NULL;
}
private:
Node* _root = nullptr;
};
#pragma once
#include"RBTree.h"
namespace study
{
template
class set
{
public:
struct SetKeyofT//在进行比较数据的时候需要用到
{
const K& operator()(const K& key)
{
return key;
}
};
//+typename是因为对模板取内嵌类型需要+typename告诉编译器是类型
typedef typename RBTree::const_iterator iterator;
typedef typename RBTree::const_iterator const_iterator;
iterator begin()const
{
return _t.begin();
}
iterator end()const
{
return _t.end();
}
pair insert(const K& key)
{
return _t.Insert(key);
}
private:
RBTree _t;
};
}
#pragma once
#include"RBTree.h"
namespace study
{
template
class map
{
public:
struct MapKeyOfT
{
const K& operator()(const pair& kv)
{
return kv.first;
}
};
typedef typename RBTree, MapKeyOfT>::iterator iterator;
typedef typename RBTree, MapKeyOfT>::const_iterator const_iterator;
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
V& operator[](const K& key)
{
pair ret = insert(make_pair(key, V()));
return ret.first->second;
}
pair insert(const pair& kv)
{
return _t.Insert(kv);
}
private:
RBTree, MapKeyOfT> _t;
};
}
test.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include
using namespace std;
#include"RBTree.h"
#include"Mymap.h"
#include"Myset.h"
void test_set()
{
study::set s;
s.insert(4);
s.insert(1);
s.insert(2);
s.insert(3);
s.insert(2);
s.insert(0);
s.insert(10);
s.insert(5);
study::set::iterator it = s.begin();
while (it != s.end())
{
cout << *it << endl;
it++;
}
cout << endl;
it = s.begin();
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
void test_map()
{
study::map dict;
dict.insert(make_pair("sort", ""));
dict.insert(make_pair("sort", "xx"));
dict.insert(make_pair("left", ""));
dict.insert(make_pair("right", "yy"));
//study::map::iterator it1 = dict.begin();
//while (it1 != dict.end())
//{
// // key
// //it->first += 'x';
// //it1->second += 'y';
// cout << it1->first << ":" << it1->second << endl;
// ++it1;
//}
//cout << endl;
string arr[] = { "哈密瓜", "香蕉","火龙果", "香蕉", "香蕉", "火龙果"};
study::map countMap;
for (auto& e : arr)
{
countMap[e]++;
}
for (auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
cout << endl;
}
int main()
{
test_set();
test_map();
return 0;
}