红黑树1.0
1.红黑树的概念
红黑树,是一种二叉搜索树,但在每个结点上增加一个存储位表示结点的颜色,可以是 Red 或 Black。通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出两倍,因而是接近平衡的。
2.红黑树的性质
- 每个结点不是红色就是黑色
- 根节点是黑色的
- 如果一个节点是红色的,则它的两个孩子结点是黑色的
- 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点
- 每个叶子结点都是黑色的 (此处的叶子结点指的是空结点)
3.插入情况分类
code:(待完善)
#pragma once
#include<iostream>
using namespace std;
#include<assert.h>
#include<vector>
#include <cstdlib>
#include <ctime>
//红黑树的规则
//1.每个节点不是黑色就是红色
//2.根节一定是黑色
//3.一个节点是红色,则它的子节点一定都是黑色
//4.对于每个节点,从该节点到它的后代的简单路径上,它们的黑色节点的个数一定相同
//5.每个叶子节点都是黑色,此处叶子节点指的是空节点
//枚举
enum colour
{
RED,
BLACK
};
template<class K,class V>
struct RBnode
{
pair<K, V> _kv;
colour _con;
RBnode<K, V>* _parent;
RBnode<K, V>* _left;
RBnode<K, V>* _right;
RBnode(const pair<K, V>& kv):_kv(kv),_con(RED), _parent(nullptr), _left(nullptr), _right(nullptr) {}
};
template<class K,class V>
class RBtree
{
typedef RBnode<K, V> node;
public:
RBtree():_root(nullptr) {};
bool _insert(const pair<K, V>& kv)//引用单纯是为了避免拷贝构造的开销
{
try
{
cout << "1111" << " ";
if (_root == nullptr)
{
_root= new node(kv);
_root->_con = BLACK;
return true;
}
node* cur = _root;
node* parent = nullptr;
while (cur)
{
parent = cur;
if (cur->_kv.first > kv.first)
{
cur = cur->_left;
}
else if (cur->_kv.first < kv.first)
{
cur = cur->_right;
}
else
{
return false;
}
}
cur = new node(kv);
cur->_con = RED;
cur->_parent = parent;
(parent->_kv.first > cur->_kv.first) ? (parent->_left = cur) : (parent->_right = cur);
//红黑树调整代码
while (parent&&parent->_con==RED)
{
node* grandFather = parent->_parent;
if (parent==grandFather->_left)
{
node* uncle = parent->_right;
//规则一:uncle存在且为红色,把parent和uncle变色为黑色,然后gf变为黑色,向上调整
if (uncle&&uncle->_con==RED)
{
parent->_con = BLACK;
uncle->_con = BLACK;
grandFather->_con = RED;
//继续向上调整
cur = grandFather;
parent = cur->_parent;
}
else//情况二
{
if (cur == parent->_left)
{
// g
// p
//c
//cur在父亲的左
RotateR(grandFather);
parent->_con = BLACK;
grandFather->_con = RED;
}
else
{
// g
// p
// c
RotateL(parent);
RotateR(grandFather);
cur->_con = BLACK;
grandFather->_con = RED;
}
}
}
else if (parent == grandFather->_right)
{
node* uncle = grandFather->_left;
if (uncle && uncle->_con == RED)
{
parent->_con = BLACK;
uncle->_con = BLACK;
grandFather->_con = RED;
//继续向上调整
cur = grandFather;
parent = cur->_parent;
}
else
{
if (cur == parent->_right)
{
RotateL(grandFather);
parent->_con = BLACK;
grandFather->_con = RED;
/
//cur = parent; // 关键修复:cur 指向新的父节点
//parent = cur->_parent; // parent 更新为 cur 的父节点
}
else
{
// g
// u p
// c
RotateR(parent);
RotateL(grandFather);
cur->_con = BLACK;
grandFather->_con = RED;
/*parent = cur->_parent; */ // parent 指向 cur 的新父节点
}
break;
}
}
}
_root->_con = BLACK;//不管最后结果如何一定要确保根节点为黑色
}
catch (const std::exception&e)
{
cout << "抛异常:" << " ";
cout << e.what() << endl;
}
return true;
}
void inorder()
{
cout << "中序遍历:" << " ";
_inorder(_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);
}
int height()
{
return _Height(_root);
}
size_t _size(node* root)
{
if (root == nullptr)
return 0;
return _size(root->_left) + _size(root->_right) + 1;
}
bool check(node* root,int blacknum,const int rev)
{
if (root == nullptr)
{
if (rev != blacknum)
{
cout << "存在黑色节点数量不相等!" << endl;
return false;
}
return true;
}
if (root->_con == RED && root->_parent->_con == RED)
{
//这里很巧妙的处理连续红色检查,因为儿子有两个、
// ,但是父亲只有一个检查父亲和root然后进行一个递归就可以查出所有的连续红色
cout << "出现连续的红色" << endl;
return false;
}
if (root->_con == BLACK)
{
++blacknum;
}
return check(root->_left,blacknum,rev) && check(root->_right,blacknum,rev);
}
bool isbalance()
{
if (_root == nullptr)
return true;
if (_root->_con == RED)
{
return false;
}
int rev = 0;
node* cur = _root;
if (cur->_con == BLACK)
{
++rev;
}
int blacknum = 0;
return check(_root,blacknum,rev);
}
private:
void _inorder(node* root)
{
if (root == nullptr)
return;
_inorder(root->_left);
cout << root->_kv.first << " ";
_inorder(root->_right);
}
void RotateL(node* parent)
{
node* p_parent = parent->_parent;
node* subR = parent->_right;
node* subRL = subR->_right;
parent->_right = subRL;
subR->_left = parent;
parent->_parent = subR;
if (subRL)
subRL->_parent = parent;
if (_root == parent)
{
_root = subR;
subR->_parent = nullptr;
}
else
{
if (p_parent->_left == parent)//记住因为此时原树并没有被摧毁,parent节点也还没有更新,并不是说树的指针只能有两个指向
{
p_parent->_left = subR;
}
else if(p_parent->_right==parent)
{
p_parent->_right = subR;
}
subR->_parent = p_parent;
}
}
void RotateR(node* parent)
{
if (parent == nullptr) return;
node* subL = parent->_left;
node* subLR = subL->_right;
node* p_parent = parent->_parent;
subL->_right = parent;
parent->_left = subLR;
if (subLR)
{
subLR->_parent = parent;
}
if (_root == parent)
{
_root = subL;
subL->_parent = nullptr;
}
else
{
if (p_parent->_left == parent)
{
p_parent->_left = subL;
}
else if (p_parent->_right == parent)
{
p_parent->_right = subL;
}
else
{
assert(false);
}
subL->_parent = p_parent;
}
}
node* _root=nullptr;
};