前言
使用前面实现的红黑树封装set和map,set是K模型的容器,map是KV模型的容器
改造红黑树
优化节点
enum Color
{
BLACK,
RED,
};
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
Color _col;
RBTreeNode(const T& data)
:_parent(nullptr),
_left(nullptr),
_right(nullptr),
_data(data),
_col(RED)
{}
};
将之前的双参数<class K, class V>改为一个参数< class T>,
优化红黑树
// set->RBTree<K, K, SetKeyOfT> _t;
// map->RBTree<K, pair<const K, V>, MapKeyOfT> _t;
template<class K, class T,class KeyOfT> // 多传了一个仿函数,用于比较节点
class RBTree
{
typedef RBTreeNode<T> Node;
public:
bool Insert(const T& data)
{
// 1.按搜索树的规则进行插入
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return true;
}
KeyOfT koft; // 定义一个仿函数
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (koft(data) < koft(cur->_data)) // 获取set的K,或者pair里的K进行比较
{
parent = cur;
cur = cur->_left;
}
else if (koft(data) > koft(cur->_data))
{
parent = cur;
cur = cur->_right;
}
else
{
return false; // 这里不能写break
}
}
cur = new Node(data);
Node* newnode = cur;
if (koft(parent->_data) < koft(data))
{
parent->_right = cur;
}
else if (koft(parent->_data) > koft(data))
{
parent->_left = cur;
}
cur->_parent = parent;
// 新增红的结点
cur->_col = RED;
while (parent && parent -> _col == RED)
{
// 红黑色的条件关键看叔叔
Node* grandfather = parent->_parent;
if (grandfather->_left == parent)
{
Node* uncle = grandfather->_right;
// 情况1:uncle存在,且为红
// 情况2 or 情况3:uncle不存在 or uncle存在,且为黑
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandfather->_col = RED;
// 继续往上处理
cur = grandfather;
parent = cur->_parent; // 如果parent为空,即cur为_root,直接在最后将根变黑
}
else
{
// 情况三:双旋 -> 单旋
if (cur == parent->_right)
{
RotateL(parent);
swap(parent, cur);
}
// 第二种情况(ps:有可能是第三种变过来的)
RotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
break;
}
}
else if (grandfather->_right == parent)
{
Node* uncle = grandfather->_left;
// 情况1:uncle存在,且为红
// 情况2 or 情况3:uncle不存在 or uncle存在,且为黑
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandfather->_col = RED;
// 继续往上处理
cur = grandfather;
parent = cur->_parent; // 如果parent为空,即cur为_root,直接在最后将根变黑
}
else
{
// 情况三:双旋 -> 单旋
if (cur == parent->_left)
{
RotateR(parent);
swap(parent, cur); // 交换的两个结点的指针
}
// 第二种情况(ps:有可能是第三种变过来的)
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
break;
}
}
}
_root->_col = BLACK;
return true;
}
// 左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRLeft = subR->_left;
parent->_right = subRLeft;
if (subRLeft)
{
subRLeft->_parent = parent;
}
Node* pparent = parent->_parent;
subR->_left = parent;//
parent->_parent = subR;
// parent 是根
// parent 不是根
if (_root == parent)
{
_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* subLRight = subL->_right;
parent->_left = subLRight;
if (subLRight)
{
subLRight->_parent = parent;
}
Node* pparent = parent->_parent;
subL->_right = parent; //
parent->_parent = subL;
// parent 是根
// parent 不是根
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (pparent->_left == parent)
{
pparent->_left = subL;
}
else
{
pparent->_right = subL;
}
subL->_parent = pparent;
}
}
bool find(const K& key)
{
KeyOfT koft;
Node* cur = _root;
while (cur)
{
if (koft(cur->_data) > key)
cur = cur->left;
else if (koft(cur->_data) < key)
cur = cur->right;
else
return true;
}
return false;
}
void _InOrder(Node* root) // 注意是Node* 类型的
{
if (root == nullptr) return;
_InOrder(root->_left);
//cout << root->_kv.first << " " << root->_kv.second << endl;
_InOrder(root->_right);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
private:
Node* _root = nullptr;
};
没有迭代器的set和map
set.h
#include"RBTree2.h"
template<class K>
class set
{
struct SetKeyOfT // 仿函数返回k
{
const K& operator()(const K& k)
{
return k;
}
};
public:
pair<iterator,bool> Insert(const K& k)
{
return _t.Insert(k);
}
private:
RBTree<K, K,SetKeyOfT> _t;
};
map.h
#include"RBTree2.h"
template<class K,class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)// 仿函数返回k
{
return kv.first;
}
};
public:
bool Insert(const pair<const K,V>& kv)
{
return _t.Insert(kv);
}
private:
RBTree<K, pair<const K,V>, MapKeyOfT> _t;
};
实现迭代器
迭代器的好处是可以方便遍历,是数据结构的底层实现与用户透明。如果想要给红黑树增加迭代器,需要考虑以前问题:begin()与end()
STL明确规定,begin()与end()代表的是一段前闭后开的区间,而对红黑树进行中序遍历后,可以得到一个有序的序列,因此:begin()可以放在红黑树中最小节点(即最左侧节点)的位置,end()放在最大节点(最右侧节点)的下一个位置,关键是最大节点的下一个位置在哪块?
能否给成nullptr呢?答案是行不通的,因为对end()位置的迭代器进行--操作,必须要能找最后一个元素,此处就不行,因此最好的方式是下图
由于没有实现头结点,无法实现倒序打印
迭代器封装
template<class T,class Ref,class Ptr>
class __TreeIterator
{
typedef RBTreeNode<T> Node;
public:
typedef __TreeIterator<T, Ref, Ptr> Self;
//如果Ref和Ptr都是非const,则下面与上面没区别,但如果是const,则下面仍是非const,
//typedef __TreeIterator<T, T&, T*> Self;
typedef __TreeIterator<T, T&, T*> iterator;
Node* _node;
__TreeIterator(Node* node)
:_node(node)
{}
// 普通迭代器的时候,他是拷贝构造
// const迭代器的时候,他是构造,支持用普通迭代器构造const迭代器
__TreeIterator(const iterator& s)//加上这个,就满足普通迭代器赋值给const迭代器
:_node(s._node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()
{
// 1、如果右不为空,中序的下一个就是右子树的最左节点
// 2、如果右为空,表示_node所在的子树已经完成,在下一个节点在他的祖先中找
// 沿着路径往上找孩子是它的左的那个祖先
if (_node->_right)// 右不为空
{
// 中序的下一个就是右子树的最左节点
Node* subLeft = _node->_right;
while (subLeft->_left)
{
subLeft = subLeft->_left;
}
_node = subLeft;
}
else // 右为空
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
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;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator==(const Self& s)
{
return _node == s._node;
}
};
迭代器的++操作
1、如果右不为空,中序的下一个就是右子树的最左节点
2、如果右为空,表示_node所在的子树已经完成,下一个节点在他的祖先中找
沿着路径往上找孩子是它的左的那个祖先
Self& operator++()
{
// 1、如果右不为空,中序的下一个就是右子树的最左节点
// 2、如果右为空,表示_node所在的子树已经完成,在下一个节点在他的祖先中找
// 沿着路径往上找孩子是它的左的那个祖先
if (_node->_right)// 右不为空
{
// 中序的下一个就是右子树的最左节点
Node* min = _node->_right;
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else // 右为空
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
迭代器的--操作
1、如果左不为空,中序的上一个就是左子树的最右节点
2、如果左为空,表示_node所在的子树已经完成,下一个节点在他的祖先中找
沿着路径往上找孩子是它的右的那个祖先
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 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* 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);
}
private:
Node* _root = nullptr;
};
有迭代器的set和map(完全)
红黑树(RBTree2.h)
#pragma once
enum Color
{
BLACK,
RED,
};
template<class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
T _data;
Color _col;
RBTreeNode(const T& data)
:_parent(nullptr),
_left(nullptr),
_right(nullptr),
_data(data),
_col(RED)
{}
};
template<class T,class Ref,class Ptr>
class __TreeIterator
{
typedef RBTreeNode<T> Node;
public:
typedef __TreeIterator<T, Ref, Ptr> Self;
//如果Ref和Ptr都是非const,则下面与上面没区别,但如果是const,则下面仍是非const,
//typedef __TreeIterator<T, T&, T*> Self;
typedef __TreeIterator<T, T&, T*> iterator;
Node* _node;
__TreeIterator(Node* node)
:_node(node)
{}
// 普通迭代器的时候,他是拷贝构造
// const迭代器的时候,他是构造,支持用普通迭代器构造const迭代器
__TreeIterator(const iterator& s)//加上这个,就满足普通迭代器赋值给const迭代器
:_node(s._node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
Self& operator++()
{
// 1、如果右不为空,中序的下一个就是右子树的最左节点
// 2、如果右为空,表示_node所在的子树已经完成,在下一个节点在他的祖先中找
// 沿着路径往上找孩子是它的左的那个祖先
if (_node->_right)// 右不为空
{
// 中序的下一个就是右子树的最左节点
Node* min = _node->_right;
while (min->_left)
{
min = min->_left;
}
_node = min;
}
else // 右为空
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_right)
{
cur = cur->_parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
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;
}
bool operator!=(const Self& s)
{
return _node != s._node;
}
bool operator==(const Self& s)
{
return _node == s._node;
}
};
// set->RBTree<K, K, SetKeyOfT> _t;
// map->RBTree<K, pair<const K, V>, MapKeyOfT> _t;
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* 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<iterator,bool> Insert(const T& data)
{
// 1.按搜索树的规则进行插入
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root),true);
}
KeyOfT koft;
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (koft(data) < koft(cur->_data))
{
parent = cur;
cur = cur->_left;
}
else if (koft(data) > koft(cur->_data))
{
parent = cur;
cur = cur->_right;
}
else
{
return make_pair(iterator(cur), false); // 这里不能写break
}
}
cur = new Node(data);
Node* newnode = cur;
if (koft(parent->_data) < koft(data))
{
parent->_right = cur;
}
else if (koft(parent->_data) > koft(data))
{
parent->_left = cur;
}
cur->_parent = parent;
// 新增红的结点
cur->_col = RED;
while (parent && parent -> _col == RED)
{
// 红黑色的条件关键看叔叔
Node* grandfather = parent->_parent;
if (grandfather->_left == parent)
{
Node* uncle = grandfather->_right;
// 情况1:uncle存在,且为红
// 情况2 or 情况3:uncle不存在 or uncle存在,且为黑
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandfather->_col = RED;
// 继续往上处理
cur = grandfather;
parent = cur->_parent; // 如果parent为空,即cur为_root,直接在最后将根变黑
}
else
{
// 情况三:双旋 -> 单旋
if (cur == parent->_right)
{
RotateL(parent);
swap(parent, cur);
}
// 第二种情况(ps:有可能是第三种变过来的)
RotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
break;
}
}
else if (grandfather->_right == parent)
{
Node* uncle = grandfather->_left;
// 情况1:uncle存在,且为红
// 情况2 or 情况3:uncle不存在 or uncle存在,且为黑
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandfather->_col = RED;
// 继续往上处理
cur = grandfather;
parent = cur->_parent; // 如果parent为空,即cur为_root,直接在最后将根变黑
}
else
{
// 情况三:双旋 -> 单旋
if (cur == parent->_left)
{
RotateR(parent);
swap(parent, cur); // 交换的两个结点的指针
}
// 第二种情况(ps:有可能是第三种变过来的)
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
break;
}
}
}
_root->_col = BLACK;
return make_pair(iterator(newnode), true);
}
// 左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRLeft = subR->_left;
parent->_right = subRLeft;
if (subRLeft)
{
subRLeft->_parent = parent;
}
Node* pparent = parent->_parent;
subR->_left = parent;//
parent->_parent = subR;
// parent 是根
// parent 不是根
if (_root == parent)
{
_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* subLRight = subL->_right;
parent->_left = subLRight;
if (subLRight)
{
subLRight->_parent = parent;
}
Node* pparent = parent->_parent;
subL->_right = parent; //
parent->_parent = subL;
// parent 是根
// parent 不是根
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (pparent->_left == parent)
{
pparent->_left = subL;
}
else
{
pparent->_right = subL;
}
subL->_parent = pparent;
}
}
iterator* find(const K& key)
{
KeyOfT koft;
Node* cur = _root;
while (cur)
{
if (koft(cur->_data) > key)
cur = cur->left;
else if (koft(cur->_data) < key)
cur = cur->right;
else
return iterator(cur);
}
return iterator(nullptr);
}
void _InOrder(Node* root) // 注意是Node* 类型的
{
if (root == nullptr) return;
_InOrder(root->_left);
//cout << root->_kv.first << " " << root->_kv.second << endl;
_InOrder(root->_right);
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool IsBalance()//检查是否为红黑树结构
{
if (_root == nullptr)
{
return true;
}
if (_root->_col != BLACK)
{
return false;
}
int ref = 0;
Node* left = _root;
while (left)
{
if (left->_col == BLACK)
{
++ref;
}
left = left->_left;
}
//遍历这棵树,就好了,检查是否存在连续的红结点。
//检查父亲,因为孩子不一定有,但是一定有父亲
return Check(_root, 0, ref);
}
private:
Node* _root = nullptr;
bool Check(Node* root, int blackNum, int ref)
{
if (root == nullptr)
{
if (blackNum != ref)
{
cout << "违反规则:一条路径上的黑色节点数量不同" << endl;
return false;
}
return true;
}
if (root->_col == RED && root->_parent->_col == RED)
{
cout << "违反规则,出现连续红色结点" << endl;
}
if (root->_col == BLACK)
{
++blackNum;
}
return Check(root->_left, blackNum, ref)
&& Check(root->_right, blackNum, ref);
}
};
set.h
#pragma once
#include"RBTree2.h"
namespace hek
{
template<class K>
class set
{
struct SetKeyOfT // 仿函数返回k
{
const K& operator()(const K& k)
{
return k;
}
};
public:
//加上typename是由于没有实例化的模板不能进行typedef。
//由于set是不能修改的,因此均用const
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& k)
{
pair<typename RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(k);
return pair<iterator, bool>(ret.first, ret.second);
//return _t.Insert(k);
}
private:
RBTree<K, K,SetKeyOfT> _t;
};
void test_set2(const set<int>& s)
{
set<int>::const_iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
set<int>::const_iterator rit = s.begin();
while (rit != s.end())
{
//*rit = 1; 报错
cout << *rit << " ";
--rit;
}
cout << endl;
}
void test_set()
{
set<int> s;
s.Insert(1);
s.Insert(3);
s.Insert(4);
s.Insert(2);
s.Insert(5);
test_set2(s);
set<int>::iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
}
map.h
#pragma once
#include"RBTree2.h"
namespace hek
{
template<class K,class V>
class map
{
struct MapKeyOfT
{
const K& operator()(const pair<K, V>& kv)// 仿函数返回k
{
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();
}
pair<iterator,bool> Insert(const pair<const K,V>& kv)
{
return _t.Insert(kv);
}
V& operator[](const K& key)
{
pair<iterator,bool> ret = _t.Insert(make_pair(key, V()));
// class T类型 是一个pair
return ret.first->second;
// ret.first >> 树的结点 节点存pair<K,V>
}
private:
RBTree<K, pair<const K,V>, MapKeyOfT> _t;
};
void test_map2(const map<int,int>& s)
{
map<int,int>::const_iterator it = s.begin();
while (it != s.end())
{
cout << it->first << " " << it->second << endl;
++it;
}
cout << endl;
}
void test_map()
{
map<int, int> m;
m.Insert(make_pair(1, 1));
m.Insert(make_pair(3, 3));
m.Insert(make_pair(6, 6));
m.Insert(make_pair(7, 3));
m.Insert(make_pair(8, 3));
test_map2(m);
map<int, int>::iterator it = m.begin();
while (it != m.end())
{
cout << it->first << " " << it->second << endl;
++it;
}
cout << endl;
string strArr[] = { "西瓜","西瓜","桃子","橘子","柚子","葡萄","黄瓜","西瓜","西瓜" };
map<string, int> countMap;
for (auto& str : strArr)
{
// 1、如果水果不在map中,则operator[]会插入pair<str,0( int() )>,返回映射对象(次数)的引用进行了++
// 2、如果水果在map中,则operator[]返回水果对应的映射对象(次数)的引用,对它++。.
countMap[str]++;
}
for (auto& i : countMap)
{
cout << i.first << ":" << i.second << endl;
}
}
}
test.cpp
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include"RBTree2.h"
#include"map.h"
#include"set.h"
int main()
{
hek::test_map();
hek::test_set();
return 0;
}