目录
一,红黑树部分
1.模板参数![](https://img-blog.csdnimg.cn/direct/af16ada28dd544ce9721b319411c5f76.png)
K为find是通过K的类型去查找,T为红黑树中节点的类型,KeyOFT为比较插入时需要拿到T中的KEY参数。
如何实现KeyOFT仿函数 细节:
在MySet类中,我们知道此时的节点为单参数Key,所以直接返回值就可以。
在MyMap类中,我们知道此时的节点为一个pair,所以返回pair的第一个参数用作比较插入。
2.节点插入部分
细节:看代码注释
std::pair<Iterator,bool> insert(const T& t) {
if (_root == nullptr) {
_root = new Node(t);
return std::make_pair(_root,true);
}
KeyOFT kot;
Node* parent = _root;
Node* cur = _root;
while (cur) {
if (kot(cur->_data) > kot(t)) {
parent = cur;
cur = cur->_left;
}
else if (kot(cur->_data) < kot(t)) {
parent = cur;
cur = cur->_right;
}
else {
return std::make_pair(cur, false);
}
}
cur = new Node(t);
Node* recur = cur;
if (kot(t) < kot(parent->_data)) {
parent->_left = cur;
cur->_parent = parent;
}
else if (kot(t) > kot(parent->_data)) {
parent->_right = cur;
cur->_parent = parent;
}
else {
return std::make_pair(cur, false);
}
while (parent && parent->_col == RED) {
Node* grandFather = parent->_parent;
if (grandFather == nullptr) {
break;
}
if (grandFather&&parent == grandFather->_left) {
// g
// p u
Node* uncle = grandFather->_right;
//叔叔存在且为红,只需向上变色即可
if (uncle && uncle->_col == RED) {
parent->_col = BLACK;
uncle->_col = BLACK;
grandFather->_col = RED;
//继续向上处理
cur = grandFather;
parent = grandFather->_parent;
}
//叔叔不存在或者为黑,需要旋转,不需要再向上处理
else {
if (cur == parent->_left) {
// g
// p u
//c
RotateR(grandFather);
parent->_col = BLACK;
grandFather->_col = RED;
break;
}
else if (cur == parent->_right){
// g
// p u
// c
RotateL(parent);
RotateR(grandFather);
cur->_col = BLACK;
parent->_col = RED;
grandFather->_col = RED;
break;
}
else {
assert(false);
}
}
}
else if (grandFather && parent == grandFather->_right) {
// g
// u p
Node* uncle = grandFather->_left;
//叔叔存在且为红,只需向上变色即可
if (uncle && uncle->_col == RED) {
parent->_col = BLACK;
uncle->_col = BLACK;
grandFather->_col = RED;
//继续向上处理
cur = grandFather;
parent = grandFather->_parent;
}
//叔叔不存在或者为黑,需要旋转,不需要再向上处理
else {
if (cur == parent->_left) {
// g
// u p
// c
RotateR(parent);
RotateL(grandFather);
parent->_col = RED;
grandFather->_col = RED;
cur->_col = BLACK;
break;
}
else if (cur == parent->_right) {
// g
// u p
// c
RotateL(grandFather);
parent->_col = BLACK;
grandFather->_col = RED;
break;
}
else {
assert(false);
}
}
}
else {
assert(false);
}
}
//保证根节点为黑
_root->_col = BLACK;
return std::make_pair(recur, true);
}
3.验证树是否是红黑树
以接口的形式提供给外部,因为外部拿不到根节点。
细节:
先将一条路走到底,然后返回一共有多少黑节点,将此数据作为参考数据,然后遍历整棵树走到空的时候,对比参考数据,不相等则违反了每条路径的黑节点相等规则。
在遍历树的过程中,如果父节点和子节点都为红节点,则违反了红节点不相邻规则
4.旋转实现
细节图在往期中有画,这里附上源码
void RotateL(Node* parent) {
Node* nodeR = parent->_right;
Node* nodeRL = nodeR->_left;
if (nodeRL) {
nodeRL->_parent = parent;
}
Node* ppNode = parent->_parent;
if (ppNode) {
if (ppNode->_left == parent) {
ppNode->_left = nodeR;
nodeR->_parent = ppNode;
}
else {
ppNode->_right = nodeR;
nodeR->_parent = ppNode;
}
}
else {
_root = nodeR;
nodeR->_parent = nullptr;
}
nodeR->_left = parent;
parent->_right = nodeRL;
parent->_parent = nodeR;
}
void RotateR(Node* parent) {
Node* nodeL = parent->_left;
Node* nodeLR = nodeL->_right;
if (nodeLR) {
nodeLR->_parent = parent;
}
Node* ppNode = parent->_parent;
if (ppNode) {
if (ppNode->_left == parent) {
nodeL->_parent = ppNode;
ppNode->_left = nodeL;
}
else {
nodeL->_parent = ppNode;
ppNode->_right = nodeL;
}
}
else {
_root = nodeL;
nodeL->_parent = nullptr;
}
parent->_left = nodeLR;
parent->_parent = nodeL;
nodeL->_right = parent;
}
二,迭代器部分
1.前置加加的实现
细节;
当此节点的右节点不为空时,找到右子树的最左节点,此时为当前节点的下一个节点
当右节点为空时,此时以此节点为根的整棵树都遍历完成,这是向上找到parent左边为cur的parent节点,此时parent为下一个需遍历节点。
注:减减逻辑与加加相反,这里不多加赘述,后置加加与减减直接复用前置的代码即可实现,封装源码部分有实现哦
self& operator++() {
if (_node->_right) {
Node* rightNode = _node->_right;
Node* LeftMinNode = rightNode;
while (LeftMinNode->_left) {
LeftMinNode = LeftMinNode->_left;
}
_node = LeftMinNode;
}
else{
Node* parent = _node->_parent;
Node* cur = _node;
while (parent && parent->_right == cur) {
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
2.保证set和map对应的Key不能被修改。
细节:封装时传入对应的节点参数使用const修饰
3.map方括号的实现
细节:
调用insert函数,insert返回一个pair,pair第一个参数为指向节点的迭代器,因为重载了-> ,所以迭代器调用second——首先调用->函数找到pair的地址,再去找到second,因为第二个参数可以修改,所以返回second的引用
三,封装源码
这里附上封装源码,分为四个文件进行封装
#pragma once
#include<assert.h>
#include<iostream>
namespace yuan {
enum Colour {
RED,
BLACK
};
template<class T>
struct RBNode {
typedef RBNode<T> Node;
Node* _left;
Node* _right;
Node* _parent;
T _data;
Colour _col ;
RBNode(const T& data)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(data)
, _col(RED)
{}
};
template<class T,class Ref, class Ptr>
struct IteratorRBtree {
typedef IteratorRBtree<T, Ref, Ptr> self;
typedef RBNode<T> Node;
Node* _node;
IteratorRBtree(Node* node)
:_node(node)
{}
Ptr operator->() {
return &_node->_data;
}
Ref operator*() {
return _node->_data;
}
bool operator!=(const self& s) {
return _node != s._node;
}
self& operator++() {
if (_node->_right) {
Node* rightNode = _node->_right;
Node* LeftMinNode = rightNode;
while (LeftMinNode->_left) {
LeftMinNode = LeftMinNode->_left;
}
_node = LeftMinNode;
}
else{
Node* parent = _node->_parent;
Node* cur = _node;
while (parent && parent->_right == cur) {
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
self operator++(int) {
self temp(this->_node);
++(*this);
return temp;
}
};
template<class K,class T,class KeyOFT>
class RBTree {
public:
typedef RBNode<T> Node;
typedef IteratorRBtree<T, T&, T*> Iterator;
typedef IteratorRBtree<T, const T&, const T*> const_Iterator;
Iterator begin() {
Node* cur = _root;
while (cur->_left) {
cur = cur->_left;
}
return cur;
}
Iterator end() {
return nullptr;
}
const_Iterator end() const{
return nullptr;
}
const_Iterator begin() const {
Node* cur = _root;
while (cur->_left) {
cur = cur->_left;
}
return cur;
}
Iterator find(const K& t) {
KeyOFT kot;
Node* cur = _root;
while (cur) {
if (kot(cur->_data) > t) {
cur = cur->_left;
}
else if (kot(cur->_data) < t) {
cur = cur->_right;
}
else {
return cur;
}
}
return nullptr;
}
std::pair<Iterator,bool> insert(const T& t) {
if (_root == nullptr) {
_root = new Node(t);
return std::make_pair(_root,true);
}
KeyOFT kot;
Node* parent = _root;
Node* cur = _root;
while (cur) {
if (kot(cur->_data) > kot(t)) {
parent = cur;
cur = cur->_left;
}
else if (kot(cur->_data) < kot(t)) {
parent = cur;
cur = cur->_right;
}
else {
return std::make_pair(cur, false);
}
}
cur = new Node(t);
Node* recur = cur;
if (kot(t) < kot(parent->_data)) {
parent->_left = cur;
cur->_parent = parent;
}
else if (kot(t) > kot(parent->_data)) {
parent->_right = cur;
cur->_parent = parent;
}
else {
return std::make_pair(cur, false);
}
while (parent && parent->_col == RED) {
Node* grandFather = parent->_parent;
if (grandFather == nullptr) {
break;
}
if (grandFather&&parent == grandFather->_left) {
// g
// p u
Node* uncle = grandFather->_right;
//叔叔存在且为红,只需向上变色即可
if (uncle && uncle->_col == RED) {
parent->_col = BLACK;
uncle->_col = BLACK;
grandFather->_col = RED;
//继续向上处理
cur = grandFather;
parent = grandFather->_parent;
}
//叔叔不存在或者为黑,需要旋转,不需要再向上处理
else {
if (cur == parent->_left) {
// g
// p u
//c
RotateR(grandFather);
parent->_col = BLACK;
grandFather->_col = RED;
break;
}
else if (cur == parent->_right){
// g
// p u
// c
RotateL(parent);
RotateR(grandFather);
cur->_col = BLACK;
parent->_col = RED;
grandFather->_col = RED;
break;
}
else {
assert(false);
}
}
}
else if (grandFather && parent == grandFather->_right) {
// g
// u p
Node* uncle = grandFather->_left;
//叔叔存在且为红,只需向上变色即可
if (uncle && uncle->_col == RED) {
parent->_col = BLACK;
uncle->_col = BLACK;
grandFather->_col = RED;
//继续向上处理
cur = grandFather;
parent = grandFather->_parent;
}
//叔叔不存在或者为黑,需要旋转,不需要再向上处理
else {
if (cur == parent->_left) {
// g
// u p
// c
RotateR(parent);
RotateL(grandFather);
parent->_col = RED;
grandFather->_col = RED;
cur->_col = BLACK;
break;
}
else if (cur == parent->_right) {
// g
// u p
// c
RotateL(grandFather);
parent->_col = BLACK;
grandFather->_col = RED;
break;
}
else {
assert(false);
}
}
}
else {
assert(false);
}
}
_root->_col = BLACK;
return std::make_pair(recur, true);
}
bool TestTree() {
int refNum = 0;
Node* cur = _root;
while (cur) {
if (cur->_col == BLACK) {
refNum++;
}
cur = cur->_left;
}
return _TestTree(_root, refNum,0);
}
private:
bool _TestTree(Node* root,int refNum,int BlackNum) {
if (root == nullptr) {
if (refNum != BlackNum) {
std::cout << "存在黑色节点的数量不相等的路径" << std::endl;
return false;
}
return true;
}
if (root->_col == BLACK) {
BlackNum++;
}
if (root->_parent && root->_parent->_col == RED && root->_col == RED) {
std::cout << "存在连续红节点" << std::endl;
return false;
}
return _TestTree(root->_left, refNum, BlackNum)
&& _TestTree(root->_right, refNum, BlackNum);
}
Node* _root = nullptr;
void RotateL(Node* parent) {
Node* nodeR = parent->_right;
Node* nodeRL = nodeR->_left;
if (nodeRL) {
nodeRL->_parent = parent;
}
Node* ppNode = parent->_parent;
if (ppNode) {
if (ppNode->_left == parent) {
ppNode->_left = nodeR;
nodeR->_parent = ppNode;
}
else {
ppNode->_right = nodeR;
nodeR->_parent = ppNode;
}
}
else {
_root = nodeR;
nodeR->_parent = nullptr;
}
nodeR->_left = parent;
parent->_right = nodeRL;
parent->_parent = nodeR;
}
void RotateR(Node* parent) {
Node* nodeL = parent->_left;
Node* nodeLR = nodeL->_right;
if (nodeLR) {
nodeLR->_parent = parent;
}
Node* ppNode = parent->_parent;
if (ppNode) {
if (ppNode->_left == parent) {
nodeL->_parent = ppNode;
ppNode->_left = nodeL;
}
else {
nodeL->_parent = ppNode;
ppNode->_right = nodeL;
}
}
else {
_root = nodeL;
nodeL->_parent = nullptr;
}
parent->_left = nodeLR;
parent->_parent = nodeL;
nodeL->_right = parent;
}
/*void _order(Node* root) {
if (root == nullptr) {
return;
}
_order(root->_left);
std::cout << root->_data << " ";
_order(root->_right);
}*/
};
}
#pragma once
#include"Encapsulation_of_Map_and_Set.h"
using namespace yuan;
template<class T>
class MySet {
public:
struct KeyOFSet {
const T& operator()(const T& Key) {
return Key;
}
};
typedef typename RBTree<T, const T, KeyOFSet>::Iterator iterator;
iterator begin() {
return _root.begin();
}
iterator end() {
return _root.end();
}
std::pair<iterator, bool> insert(const T& t) {
return _root.insert(t);
}
iterator find(const T& t) {
return _root.find(t);
}
bool testTree() {
return _root.TestTree();
}
private:
RBTree<T,const T, KeyOFSet> _root;
};
#pragma once
#include"Encapsulation_of_Map_and_Set.h"
using namespace yuan;
template<class K,class V>
class MyMap {
struct KeyOFMAP {
const K& operator()(const std::pair<K, V>& p) {
return p.first;
}
};
public:
typedef typename RBTree<K, std::pair<const K, V>, KeyOFMAP>::Iterator iterator;
iterator begin() {
return _root.begin();
}
iterator end() {
return _root.end();
}
std::pair<iterator,bool> insert(const std::pair<const K, V>& p) {
return _root.insert(p);
}
iterator find(const K& t) {
return _root.find(t);
}
V& operator[](const K& k) {
std::pair<iterator,bool> temp=_root.insert(std::make_pair(k, V()));
return temp.first->second;
}
bool testTree() {
return _root.TestTree();
}
private:
RBTree<K, std::pair<const K, V>, KeyOFMAP> _root;
};
#include"Encapsulation_of_Map_and_Set.h"
#include"MySet.h"
#include"MyMap.h"
using namespace yuan;
void testSet() {
MySet<int> s;
s.insert(4);
std::cout << s.testTree() << std::endl;
s.insert(2);
std::cout << s.testTree() << std::endl;
s.insert(5);
std::cout << s.testTree() << std::endl;
s.insert(15);
std::cout << s.testTree() << std::endl;
s.insert(7);
std::cout << s.testTree() << std::endl;
s.insert(1);
std::cout << s.testTree() << std::endl;
s.insert(5);
std::cout << s.testTree() << std::endl;
s.insert(7);
MySet<int>::iterator it = s.begin();
/*while (it != s.end()) {
std::cout << *it << " ";
++it;
}*/
/*for (int i = 0; i < 1000; i++) {
std::cout << i << "->" << s.testTree() << std::endl;
}*/
std::cout << s.testTree() << std::endl;
}
void testMap() {
MyMap<int, int> m1;
std::srand(time(0));
int temp;
for (int i = 0; i < 10; i++) {
temp = i + rand();
m1[temp] = rand();
//std::cout <<i<<"->"<< m1.testTree()<<std::endl;
}
MyMap<int, int>::iterator it = m1.begin();
while (it != m1.end()) {
if (it->first == 9) {
int s = 0;
}
std::cout << it->first << " " << it->second << std::endl;
it++;
}
///*++it;
//std::cout<<m1.find(3)->second;*/
//std::cout << m1[9] << std::endl; i << "->"
//std::cout << m1.testTree() << std::endl;
}
int main() {
testMap();
return 0;
}