# 红与黑之歌，map与set的底层----红黑树（自实现）

22 篇文章 0 订阅

## 红黑树的性质：

1. 每个结点不是红色就是黑色

2. 根节点是黑色的

3. 如果一个节点是红色的，则它的两个孩子结点是黑色的

4. 对于每个结点，从该结点到其所有后代叶结点的简单路径上，均 包含相同数目的黑色结点

5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

## 自实现代码：

#pragma once
#include<iostream>
#include<set>
using namespace std;

enum Color
{
RED,
BLACK
};

template<class T>
class RBTreeNode
{
public:
T _Data;
RBTreeNode* _left;
RBTreeNode* _parent;
RBTreeNode* _right;
Color _col;

RBTreeNode(const T&data)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_Data(data)
{}
};

//迭代器
template<class T>
class RBTreeIterator
{
public:
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T> self;
Node* _node;
Node* _root;

RBTreeIterator(Node*node,Node*root)
:_node(node)
,_root(root)
{}

self& operator++()
{
Node* leftMost = _node->_right;

if (_node->_right)
{
leftMost = leftMost->_left;
while (leftMost)
{
leftMost = leftMost->_left;
}
_node = leftMost;
}
else
{
Node* current = _node;
Node* parent = _node->_parent;

if (parent && parent->_right == current)
{
/*parent = parent->_parent;
cur = parent;*/
current = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}

self& operator--()
{
if (_node == nullptr)
{
//找最右节点
Node* rightMost = _root;
while (rightMost && rightMost->_right)
{
rightMost = rightMost->_right;
}

_node = rightMost;
}
else if (_node->_left)
{
Node* rightMost = _node->_left;
while (rightMost->_right)
{
rightMost = rightMost->_right;
}

_node = rightMost;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = cur->_parent;
}

_node = parent;

}

return *this;
}

T& operator*()
{
return _node->_Data;
}

bool operator!= (const self& s)
{
return _node != s._node;
}

bool operator== (const self& s)
{
return _node == s._node;
}
};

//红黑树的实现
template<class K,class T,class K_of_T>
class RBTree

public:
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T> iterator;

RBTree() = default;

//构造函数
RBTree(const T&root)
:_root(root)
{}

//拷贝构造函数,树形节点要一个一个拷贝
RBTree(const RBTree& h)
{
_root = copy(h._root);
}

//重载=
RBTree& operator=(RBTree h)
{
swap(_root, h._root);
return *this;
}

//析构函数,注意开辟了空间后，对于树形结构的节点要一个一个删除
~RBTree()
{
Destory(_root);
_root = nullptr;
}

iterator Begin()
{
Node* leftMost = _root;
while (leftMost && leftMost->_left)
{
leftMost = leftMost->_left;
}
return iterator(leftMost,_root);
}

iterator End()
{
return iterator(nullptr,_root);
}

//寻找
Node* Find(const K& key)
{
K_of_T kot;
Node* cur = _root;
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)
{
//空树新增节点，也是红黑树
Node* root = _root;
if (root == nullptr)
{
root = new Node(data);
_root = root;
_root->_col = BLACK;
return make_pair(iterator(_root, _root), true);
}

//红黑树大逻辑
K_of_T kot;
Node* cur = _root;
Node* parent = nullptr;

//要先找到，插入位置
while (cur)
{
if (kot(data) < kot(cur->_Data))
{
parent = cur;
cur = cur->_left;
}
else if (kot(data) > kot(cur->_Data))
{
parent = cur;
cur = cur->_right;
}
else
{
return make_pair(iterator(cur, _root), false);
}
}

cur = new Node(data);
// 新增节点。颜色红色给红色
cur->_col = RED;
Node* newNode = cur;
if (kot(parent->_Data) < kot(data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;

//更改颜色
//现在cur为新增节点
while (parent && parent->_col==RED)
{
Node* grandfather = parent->_parent;

//找出叔叔节点
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
//情况一
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//情况二
//    g
//  p   u
//c
if (parent->_left == cur)
{
RotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
else
{
//情况三
//    g
//  p   u
//    c
//
//双旋
RotateL(parent);
RotateR(grandfather);

//注意cur与parent调了一下位置
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
else
{
Node* uncle = grandfather->_left;
//情况一
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
else
{
//情况二
//    g
//  u   p
//        c
if (cur == parent->_right)
{
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
//情况三
//    g
//  u   p
//    c
else
{
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}

//确保根节点为黑的
_root->_col = BLACK;
return make_pair(iterator(newNode, _root), true);
}

int Height()
{
return _Height(_root);
}

int Size()
{
return _Size(_root);
}

//中序有序，避免了_root是内部private的加密
void _InOrder()
{
_InOrder(_root);

cout << endl;
}

//进行检验
bool IsBalance()
{
//空树也是红黑树
if (_root == nullptr)
return true;

//根节点是黑的
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);
}

private:

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);
}

//计算有效的节点
int _Size(Node* root)
{
return root == nullptr ? 0 : _Size(root->_left) + _Size(root->_right) + 1;
}

//计算树的高度，利用递归
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;
}

//中序遍历
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
//左根右；
_InOrder(root->_left);
cout << root->_kv.first << " :" << root->_kv.second << " ";
_InOrder(root->_right);
}

//左旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;

parent->_right = subRL;
if (subRL)
subRL->_parent = parent;

subR->_left = parent;
parent->_parent = subR;

Node* parent_parent = parent->_parent;
if (parent_parent == nullptr)
{
_root = subR;
parent_parent = nullptr;
}
else
{
if (parent_parent->_left == parent)
{
parent_parent->_left = subR;
}
else if (parent_parent->_right == parent)
{
parent_parent->_right = subR;
}
subR->_parent = parent_parent;
}
}

//右旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR)
subLR->_parent = parent;

subL->_right = parent;
parent->_parent = subL;

Node* parent_parent = parent->_parent;
if (parent_parent == nullptr)
{
_root = subL;
parent_parent = nullptr;
}
else
{
if (parent_parent->_left == parent)
{
parent_parent->_left = subL;
}
else if (parent_parent->_right == parent)
{
parent_parent->_right = subL;
}
subL->_parent = parent_parent;
}
}

//销毁
void Destory(Node* root)
{
if (root == nullptr)
{
return;
}
Destory(root->_left);
Destory(root->_right);
Destory(root->_parent);
delete root;
}

//拷贝
Node* copy(const Node*& root)
{
if (root == nullptr)
{
return nullptr;
}
Node* temp = new Node(root->_kv);
temp->_left = copy(root->_left);
temp->_right = copy(root->_right);
temp->_parent = copy(root->_parent);
return temp;
}

Node* _root = nullptr;
};

## 结语：本文已经实现了一部分map与set的接口，下集我们相约map与set封装，哈希等好知识点，感谢大家的支持！ 以下是一些接口：

namespace my_map
{

template<class K, class V>
class map
{
public:
struct K_of_T
{
const K& operator()(const pair<K, V>& kv)
{
return kv.first;
}
};
typedef typename RBTree<K, K, K_of_T>::iterator iterator;
iterator begin()
{
return _t.Begin();
}

iterator end()
{
return _t.End();
}
pair<iterator, bool>Insert(const pair<K, V>& kv)
{
_t.Insert(kv);
}
private:
RBTree<K, pair<K, V>, K_of_T> _t;
};
}
namespace my_set
{
template<class K>
class set
{
public:
struct K_of_T
{
const K& operator()(const K& key)
{
return key;
}
};
typedef typename RBTree<K, K, K_of_T>::iterator iterator;

iterator begin()
{
return _t.Begin();
}

iterator end()
{
return _t.End();
}

pair<iterator, bool>insert(const K& key)
{
return _t.insert(key);
}
private:
RBTree<K, K, K_of_T> _t;
};
}

• 32
点赞
• 21
收藏
觉得还不错? 一键收藏
• 0
评论
03-18 559
03-20 2202
08-17 1225
03-18 3152
04-09 237
03-15 1737
05-05 5716
11-22 412

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。