文章目录
前言
红黑树是二叉搜索树的另一种实现方式,它不同于绝对平衡的AVl树,而是一颗接近平衡的二叉搜索树;红黑树相对AVl树来说更为抽象。
一、红黑树的概念
红黑树在二叉搜索树的基础上增加一个存储位置用来存储节点的颜色,每个节点不是red就是black;红黑树直接控制的是节点的颜色(红/黑),间接控制树的最长路径不超过最短路径的二倍,从而实现接近平衡
二、红黑树的性质
1.根节点是黑色
2.如果一个节点是红色,那么它的孩子节点都是黑色
3.对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。
4.每个叶子节点的都是黑色的,叶子节点指的是空(nullptr)
三、红黑树的调整平衡的思想
1.默认插入节点的颜色
默认插入什么颜色,相当于选择违反红黑树的那一条性质,默认插入红色,则有可能违反第2条性质:红节点的孩子节点一定是黑色,也就是不允许出现连续的红色节点;默认插入黑色,则绝对的会违反第3条性质:对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。
2.控制红黑树的关键节点
红黑树重点关心的是树的颜色,需要通过操作节点的颜色;根据红黑树的性质新增节点cur的周边节点都会收到影响,cur的父节点,祖父节点,叔叔节点,最关键的就是看叔叔节点的有无和颜色,来判断什么时候需要变换节点颜色,或者旋转调整,怎么调整等操作;
3.需要调整节点颜色的情况
当cur为红色,parent为红色,grandfather为黑色,uncle存在且为红色的时候,根据第2条性质需要将parent调整为黑色,为了维护第3条性质需要在讲grandfather调整为红色,uncle调整为黑色,更新cur的位置为grandfather,parent更新为cur的parent。如果parent不是根节点,且parent为红色,那么接续重复上面的动作,如果parent是根节点,那么parent的颜色要保持是黑色。
4.需要单旋调整的情况
1.cur为红色,parent为红色,grandfather为黑色,uncle不存在为空节点
2.第2种情况由改变颜色演变而来,cur为红色,parent为红色,grandfather为黑色,uncle存在且为黑
操作为:如果parent是grandfather的right同时cur是parent的right,这时候是左单旋。如果parent是grandfather的left,同时cur是parent的left,这是时候是右单旋。
5.需要双旋调整的情况
1.cur为红色,parent为红色,grandfather为黑色,uncle不存在。
2.cur为红色,parent为红色,grandfather为黑色,uncle存在且为黑。
操作:如果parent是grandfather的左,cur是parent的右。需要先parent左单旋,后将grandfather右单旋;或者parent是grandfather的右,cur是parent的左;先将parent右单旋,grandfather左单旋;cur变为黑色,grandfather变为红色;
四、插入操作代码实现
#pragma once
#include<iostream>
namespace k
{
enum Color
{
RED,
BLACK,
};
template <class T>
struct RBTreeNode
{
RBTreeNode<T>* _left;
RBTreeNode<T>* _right;
RBTreeNode<T>* _parent;
Color _col;
T _data;
//哨兵位的头结点初始化需要无参构造,插入需要有参构造
RBTreeNode(const T& data=T())
:_left(nullptr),_right(nullptr),_parent(nullptr),_col(RED),_data(data)
{}
};
template<class T,class ref,class ptr>
struct RBTreeIterator
{
typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T,ref,ptr> self;
RBTreeIterator(Node* node)
: _node(node)
{}
//set的普通迭代器的实现需要用到单参数的构造函数隐式类型转换const的迭代器
RBTreeIterator(const RBTreeIterator<T, T&,T*>& it)
: _node(it._node)
{}
// 让迭代器具有类似指针的行为
ref operator*()
{
return _node->_data;
}
ptr operator->()
{
return &_node->_data;
}
// 然迭代器可以移动:前置/后置++
self& operator++()
{
Increament();
return *this;
}
self operator++(int)
{
self tmp(*this);
Increament();
return tmp;
}
// 然迭代器可以移动:前置/后置--
self& operator--()
{
DeIncreament();
return *this;
}
self operator--(int)
{
self tmp(*this);
DeIncreament();
return tmp;
}
// 让迭代器可以比较
bool operator!=(const self& s)const
{
return _node != s._node;
}
bool operator==(const self& s)const
{
return _node == s._node;
}
private:
void Increament()
{
//如果当前节点有右节点,就找右节点的最左节点
Node* cur = _node;
if (cur->_right)
{
cur = cur->_right;
while (cur->_left)
{
cur = cur->_left;
}
}
//没有就找孩子不是父亲的右的祖先节点
else
{
Node* parent = cur->_parent;
while (cur == parent->_right)
{
cur = parent;
parent = parent->_parent;
}
//当遇到访问根节点的下一个位置为nullptr时,找祖新不是孩子的右时
// parent会一直在根的位置死循环,所以当cur->_right是parent时说明cur在end的位置,
//_node应该为end;
if (cur->_right != parent)
{
cur = parent;
}
}
_node = cur;
}
void DeIncreament()
{
//--不存在死循环的问题,因为--不涉及比对是否走到了end
//当时当从end位置访问mostright的时候需要判断是否为头结点
if (_node->_parent->_parent == _node && _node->_col == RED)
{
_node = _node->_right;
}
else
{
//看当前节点的有没有左节点,有就找左节点的最右节点.
Node* cur = _node;
if (cur->_left)
{
cur = cur->_left;
while (cur->_right)
{
cur = cur->_right;
}
}
//没有就找孩子不是父亲的左的祖先节点
else
{
Node* parent = cur->_parent;
while (parent->_left == cur)
{
cur = cur->_parent;
parent = parent->_parent;
}
cur = parent;
}
_node = cur;
}
}
Node* _node;
};
// T: 可能是键值对<key,value>
// 可能是一个key
// 不论节点中存储的是<key, value> || key, 都是按照key来进行比较的
// KeyOfValue: 提取data中的Key
template<class K,class T, class KeyOfValue>
class RBTree
{
typedef RBTreeNode<T> Node;
public:
typedef RBTreeIterator<T, T&, T*> iterator;
typedef RBTreeIterator<T,const T&,const T*> const_iterator;
public:
RBTree()
: _size(0)
{
emptyInit();
}
RBTree(const RBTree<K,T,KeyOfValue>& rb)
{
emptyInit();
if (_head->_parent != _head)
{
_head->_parent = copy(rb._head->_parent);
}
_size = rb._size;
}
~RBTree()
{
clear();
_size = 0;
delete _head;
_head = nullptr;
}
// 插入值为data的节点
// 返回值含义:iterator代表新插入节点 bool:代表释放插入成功
std::pair<iterator, bool> insert(const T& data)
{
//如果只有哨兵位的头结点就直接与头建立连接
Node* trueHead = _head->_parent;
Node* newNode = new Node(data);
if (trueHead == _head)
{
//头结点与根节点互相为parent
_head->_left = newNode;
_head->_right = newNode;
_head->_parent = newNode;
_head->_col = BLACK;
newNode->_parent = _head;
_size++;
return std::make_pair(iterator(newNode), true);
}
//找要插入节点的位置
Node* cur = trueHead;
Node* parent = nullptr;
while (cur)
{
if (KeyOfValue()(data)<KeyOfValue()(cur->_data))
{
parent = cur;
cur = cur->_left;
}
else if (KeyOfValue()(cur->_data)< KeyOfValue()(data))
{
parent = cur;
cur = cur->_right;
}
else
{
return std::make_pair(iterator(cur), false);
}
}
//插入节点
if (KeyOfValue()(data)<KeyOfValue()(parent->_data))
{
parent->_left = newNode;
}
else
{
parent->_right = newNode;
}
newNode->_parent = parent;
//cur在找位置后为空,所以更新cur
cur = newNode;
//调整节点
while (parent!=_head && parent->_col == RED)
{
//祖父的左为父亲
Node* grandfather = parent->_parent;
if (grandfather->_left == parent)
{
//叔叔存在且为红,只需调整颜色
Node* uncle = grandfather->_right;
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
//否则旋转调整
else
{
//右旋
if (cur == parent->_left)
{
rotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
//左右双旋
else
{
rotateL(parent);
rotateR(grandfather);
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
{
//左旋
if (cur == parent->_right)
{
rotateL(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
//右左双旋
else
{
rotateR(parent);
rotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
trueHead = _head->_parent;
trueHead->_col = BLACK;
_head->_left = _leftMost();
_head->_right = _rightMost();
_size++;
return std::make_pair(iterator(newNode), true);
}
// Begin和End迭代器
iterator begin()
{
return iterator(_leftMost());
}
iterator end()
{
return iterator(_head);
}
// 红黑树是否为红,是返回true,否则返回false
bool empty()const
{
return _size == 0;
}
// 返回红黑树中有效节点的个数
size_t size()const
{
return _size;
}
// 将红黑树中的有效节点删除,注意:删除的是有效节点,不删除头结点
void clear()
{
Node* cur = _head->_parent;
_destroy(cur);
_head->_parent = _head;
_head->_left = _head;
_head->_right = _head;
}
// 在红黑树中查找data,存在赶回该节点对应的迭代器,否则返回End()
iterator find(const T& data)
{
Node* cur = _head->_parent;
while (cur)
{
if (KeyOfValue()(data)< KeyOfValue()(cur->_data))
{
cur = cur->_left;
}
else if (KeyOfValue()(cur->_data)< KeyOfValue()(data))
{
cur = cur->_right;
}
else
{
return iterator(cur);
}
}
return nullptr;
}
private:
void emptyInit()
{
_head = new Node;
_head->_left = _head;
_head->_right = _head;
_head->_parent = _head;
_head->_col = RED;
}
Node* copy(Node* root)
{
Node* newNode = new Node(root->_data);
newNode->_parent = root->_parent;
newNode->_col = root->_col;
newNode->_left = copy(root->_left);
newNode->_right = copy(root->_right);
return newNode;
}
Node* _leftMost()
{
Node* cur = _head->_parent;
while (cur->_left)
{
cur = cur->_left;
}
return cur;
}
Node* _rightMost()
{
Node* cur = _head->_parent;
while (cur->_right)
{
cur = cur->_right;
}
return cur;
}
void _destroy(Node*& root)
{
if (root == nullptr)
{
return;
}
_destroy(root->_left);
_destroy(root->_right);
delete root;
root = nullptr;
}
void rotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
Node* grandfather = parent->_parent;
parent->_right = subRL;
if (subRL)subRL->_parent = parent;
subR->_left = parent;
parent->_parent = subR;
if (grandfather == _head)
{
_head->_parent = subR;
subR->_parent = _head;
}
else
{
if(grandfather->_left == parent)
{
grandfather->_left = subR;
}
else
{
grandfather->_right = subR;
}
subR->_parent = grandfather;
}
}
void rotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
Node* grandfather = parent->_parent;
parent->_left = subLR;
if (subLR)subLR->_parent = parent;
subL->_right = parent;
parent->_parent = subL;
if (grandfather == _head)
{
_head->_parent = subL;
subL->_parent = _head;
}
else
{
if (grandfather->_left == parent)
{
grandfather->_left = subL;
}
else
{
grandfather->_right = subL;
}
subL->_parent = grandfather;
}
}
private:
Node* _head;
size_t _size;
};
}
五、插入测试与红黑树性质检查
class RBTree
{
public:
void InOrder()
{
_InOrder(_root);
std::cout << std::endl;
}
int Height()
{
return _Height(_root);
}
bool isBalance()
{
//判断根节点是否为黑
if (_root&&_root->_colour==RED)
{
std::cout << "根节点颜色为红色" << std::endl;
return false;
}
//找任意一条路径统计黑节点数量
Node* cur = _root;
int benChmark = 0;
while (cur)
{
if (cur->_colour == BLACK)
{
benChmark++;
}
cur = cur->_left;
}
//检查所有路径黑节点是否相同,是否有连续红节点
return _Check(_root, 0, benChmark);
}
protected:
bool _Check(Node* root, int blackNum, int benChmark)
{
//检查所有路径黑节点是否相同
if (root == nullptr)
{
if (blackNum != benChmark)
{
std::cout << "某条路径黑节点数量不对" << std::endl;
return false;
}
return true;
}
if (root->_colour == BLACK)
{
blackNum++;
}
//检查是否有连续红节点
if (root->_colour == RED && root->_parent && root->_parent->_colour == RED)
{
std::cout << "存在两个连续的红节点" << std::endl;
return false;
}
return _Check(root->_left, blackNum, benChmark) && _Check(root->_right, blackNum, benChmark);
}
int _Height(Node* root)
{
if (root == nullptr)
{
return 0;
}
int left = _Height(root->_left);
int right = _Height(root->_right);
return left > right?left + 1 : right + 1;
}
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left);
std::cout << root->_kv.first << " ";
_InOrder(root->_right);
}
private:
Node* _root=nullptr;
};
void test1()
{
RBTree<int, int > t1;
size_t count = 500;
srand((int)time(0));
for (int i = 0; i < count; i++)
{
int x = rand();
t1.Insert(std::make_pair(x, x));
}
t1.InOrder();
std::cout << t1.Height() << std::endl;
std::cout << t1.isBalance() << std::endl;
}
void test2()
{
RBTree<int, int> t1;
int a[] = { 3,4,5,6,7,8,9,0,12,1,2,3,4,5,6,7,9,100 };
for (auto e : a)
{
t1.Insert(std::make_pair(e, e));
}
std::cout << t1.Find(std::make_pair(0, 0))->_kv.first << std::endl;
t1.InOrder();
std::cout << t1.Height() << std::endl;
}
int main()
{
rbtree::test1();
return 0;
}
六map和set的封装
1.解决map和set在insert内部无法统一使用key值比较的问题。
应为map和set用来查找和插入的值类型不同,set是key而map是pair<k,v>,所以红黑树为了同时适配set和map,数据参数统一为data,但是插入操作中有key值的比较,所以必须要知道set和map的key值,set本身只有key不用管,map传参传的pair<k,v>,pair<k,v>的对象也能比较,但是比较的规则是首先比较first,first小于插入的数据,就让second与之比较。不符合逾期。所以红黑树又增加了一个模板参数,用来传结构体类型,结构体内部定义了仿函数,set的仿函数返回值就是key,map的仿函数返回值是first;红黑树插入操作在比较的时候使用仿函数即可。
rbtree.hpp
2.迭代器的封装
set的key值不允许修改,但是map的V值是允许修改的,map存储的是pair对象,所以它们的共用迭代器是既要有普通迭代器也要有const迭代器;
set的普通迭代器和const迭代器都是红黑树的const的迭代器,用来限制set的值不被修改。但是set的内部的begin()和end()返回的是一个普通对象调用的普通迭代器(因为begin和end后面没有加const限制this,所以_t是普通对象),所以要在红黑树的迭代器类中加上一个普通迭代器的单参数构造函数,用于将普通迭代器隐式类型转换为const的迭代器。
map使用的是普通迭代器,因为map的中存储的时pair对象的second成员需要被修改,所以只const限制k
迭代器的++运算符重载,二叉树中序遍历的顺序是左子树–>根–>右子树,主要是看当前节点的右子树是否为空,不为空就找右子树的最左节点作为下一个节点,如果为空就往上找孩子是父亲节点的左子树的祖先节点作为下一个节点。
迭代器–运算符重载,翻转遍历二叉树中序遍历右子树–>根–>左子树,主要看当前节点的左子树是否空,不为空就找左子树的最右节点作为下一个节点,如果为空就找孩子是父亲节点的右子树的祖先节点作为下一个节点。
map内部还封装了[]运算符重载,需要改动insert的返回值为pair<iterator,bool>类型,使用[]插入key值,key存在则返回key对应的value值引用,不存在则插入key值。
map
#pragma once
#include <iostream>
#include <assert.h>
using namespace std;
enum colour
{
RED,
BLACK,
};
// 节点
template <class T>
struct rbTreeNode
{
rbTreeNode<T>* _left;
rbTreeNode<T>* _right;
rbTreeNode<T>* _parent;
colour _col;
T _data;
rbTreeNode(const T& data)
: _left(nullptr), _right(nullptr), _parent(nullptr), _col(RED), _data(data)
{
}
};
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)
{}
rbTreeIterator(const rbTreeIterator<T, T&, T*>& it)
:_node(it._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 != nullptr)
{
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 = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
self& operator--()
{
if (_node->_left != nullptr)
{
Node* subRight = _node->_left;
while (subRight->_right)
{
subRight = subRight->_right;
}
_node = subRight;
}
else
{
Node* cur = _node;
Node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
};
template <class K, class T, class keyOfT>
class rbTree
{
public:
typedef rbTreeNode<T> Node;
typedef rbTreeIterator<T, T&, T*> iterator;
typedef rbTreeIterator<T, const T&, const T*> const_iterator;
iterator begin()
{
Node* cur = _root;
while (cur->_left)
{
cur = cur->_left;
}
return iterator(cur);
}
iterator end()
{
return iterator(nullptr);
}
const_iterator begin()const
{
Node* cur = _root;
while (cur->_left)
{
cur = cur->_left;
}
return const_iterator(cur);
}
const_iterator end()const
{
return const_iterator(nullptr);
}
// 默认构造
rbTree() = default;
// 析构
~rbTree()
{
destroy(_root);
}
// 拷贝构造
rbTree(const rbTree<K, T, keyOfT>& t)
{
_root = copy(t._root);
}
pair<iterator,bool> insert(const T& data)
{
if (_root == nullptr)
{
_root = new Node(data);
_root->_col = BLACK;
return make_pair(iterator(_root),true);
}
// 找位置
Node* cur = _root;
Node* parent = nullptr;
keyOfT kot;
while (cur)
{
if (kot(data) > kot(cur->_data))
{
parent = cur;
cur = cur->_right;
}
else if (kot(data) < kot(cur->_data))
{
parent = cur;
cur = cur->_left;
}
else
{
return make_pair(iterator(cur),false);
}
}
// 插入
Node* newNode=new Node(data);
cur = newNode;
if (kot(data) < kot(parent->_data))
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
cur->_parent = parent;
// 调整
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
// parent在grandfather的左
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
// uncle存在且为红
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
cur = grandfather;
parent = cur->_parent;
}
// uncle不存在或者为黑
else
{
// cur在parent的左
if (cur == parent->_left)
{
rotateR(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
// cur在parent的右
else
{
rotateL(parent);
rotateR(grandfather);
grandfather->_col = RED;
cur->_col = BLACK;
}
break;
}
}
// parent在grandfather的右
else
{
Node* uncle = grandfather->_left;
// uncle存在且为红
if (uncle && uncle->_col == RED)
{
parent->_col = RED;
uncle->_col = RED;
grandfather->_col = BLACK;
cur = grandfather;
parent = cur->_parent;
}
// uncle不存在或者为黑
else
{
// cur在parent的右
if (cur == parent->_right)
{
rotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
// cur在parent的左
else
{
rotateR(parent);
rotateL(grandfather);
grandfather->_col = RED;
cur->_col = BLACK;
}
break;
}
}
}
_root->_col = BLACK;
return make_pair(iterator(newNode), true);
}
private:
Node* _root = nullptr;
};
map.hpp
#include"rbtree.h"
template <class K,class V>
class map
{
struct mapKeyOfT
{
const K& operator()(const pair<const K,V>& kv)
{
return kv.first;
}
};
public:
typedef typename rbTree<K, pair<const K, V>, mapKeyOfT>::iterator iterator;
pair<iterator, bool> insert(const pair<const K, V>& kv)
{
return _t.insert(kv);
}
iterator begin()
{
return _t.begin();
}
iterator end()
{
return _t.end();
}
V& operator[](const K& key)
{
pair<iterator,bool> ret = insert(make_pair(key,V()));
return ret.first->second;
}
private:
rbTree<K, pair<const K, V>, mapKeyOfT> _t;
};
void mapTest1()
{
map<string, string> dict;
dict.insert(make_pair("sort", "快速"));
dict.insert(make_pair("insert", "插入"));
dict.insert(make_pair("left", "左"));
dict.insert(make_pair("right", "右"));
for (auto e : dict)
{
cout << e.first << ":" << e.second << " ";
}
cout << endl;
map<string, string>::iterator it = dict.begin();
while (it != dict.end())
{
cout << it->first << ":" << it->second <<" ";
++it;
}
cout << endl;
}
void mapTest2()
{
string s[] = { "西瓜","西瓜","西瓜","西瓜","西瓜","香蕉","香蕉","香蕉","橘子" };
map<string, int> mapCount;
for (auto e : s)
{
mapCount[e]++;
}
for (auto kv : mapCount)
{
cout << kv.first <<" " << kv.second << " ";
}
cout << endl;
}
set.hpp
#include"rbtree.h"
template <class K>
class set
{
struct setKeyOfT
{
const K& operator()(const K& key)
{
return key;
}
};
public:
typedef typename rbTree<K, K, setKeyOfT>::const_iterator iterator;
typedef typename rbTree<K, K, setKeyOfT>::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 K& key)
{
return _t.insert(key);
}
private:
rbTree<K, K, setKeyOfT> _t;
};
struct key
{
int a;
key(int x)
:a(x)
{}
};
void setTest()
{
set<int> s;
int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
for (auto e : a)
{
s.insert(e);
}
set<int>::iterator it = s.begin();
while (it != s.end())
{
cout <<*it<<" ";
++it;
}
cout << endl;
}
main.cpp
#include"map.h"
int main()
{
mapTest2();
return 0;
}