一.了解项目功能
二.逐步实现项目功能模块及其逻辑详解
通过第二部分对项目功能的介绍,我们已经对 的功能有了大致的了解,虽然看似需要实现的功能很多,貌似一时间不知该如何下手,但我们可以分步分模块来分析这个项目的流程,最后再将各部分进行整合,所以大家不用担心,跟着我一步一步分析吧!
📌实现RBTreeNode类模板
🎏构造RBTreeNode类成员变量
🎏实现RBTreeNode类构造函数
📌实现RBTree类模板
🎏构造RBTree类成员变量
🎏实现RBTree类构造函数
🎏实现RBTree插入函数
🎏实现RBTree插入左单旋(和AVL树一样)
🎏实现RBTree插入右单旋(和AVL树一样)
🎏判断红黑树是否符合红黑树规则函数
三.项目完整代码
我们将程序运行的代码分别在三个工程文件中编辑,完整代码如下:
test.c文件
RBTree.h文件
#pragma once
#include<iostream>
#include<vector>
using namespace std;
enum Colour
{
RED,
BLACK
};
template<class K,class V>
struct RBTreeNode
{
RBTreeNode(const pair<K,V>& kv=pair<K,V>())
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_kv(kv)
,_col(RED)
{}
RBTreeNode<K, V>* _left;
RBTreeNode<K, V>* _right;
RBTreeNode<K, V>* _parent;
pair<K, V> _kv;
Colour _col;
};
template<class K,class V>
class RBTree
{
typedef RBTreeNode<K,V> Node;
public:
RBTree()
:_root(nullptr)
{}
bool Insert(const pair<K, V>& kv)
{
if (_root == nullptr)
{
_root = new Node(kv);
_root->_col = BLACK;
return true;
}
Node* cur = _root;
Node* parent = nullptr;
while (cur)//查了半天是这里少写了个循环...(好在自己查到了,去比对了一下,果然...加上就好了
{
if (cur->_kv.first < kv.first)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_kv.first > kv.first)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(kv);
cur->_col = RED;
if (parent->_kv.first < kv.first)
{
//插右边
parent->_right = cur;
}
else
{
//插左边
parent->_left = cur;
}
cur->_parent = parent;
//...控制颜色
//插入的永远是红结点
//插入的是根,把结点变红
//插入时父节点是黑,就ok了
//插入的父节点是红,看叔叔
// 叔叔是红,把父亲叔叔都变黑,把爷爷变红(然后继续向上处理)
// 叔叔是黑,旋转,转完父爷都变色
while ( parent && parent->_col == RED && parent->_parent)
{
Node* grandfather = parent->_parent;
if (parent == grandfather->_left)
{
Node* uncle = grandfather->_right;
//叔叔存在且为红
if (uncle && uncle->_col == RED)
{
//变色
parent->_col = 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;
}
}
}
else//parent == grandfather->_right
{
Node* uncle = grandfather->_left;
if (uncle && uncle->_col == RED)
{
//变色
parent->_col = uncle->_col = BLACK;
grandfather->_col = RED;
//继续向上处理
cur = grandfather;
parent = cur->_parent;
}
else
{
if (cur == parent->_left)
{
RotateR(parent);
RotateL(grandfather);
//改色
cur->_col = BLACK;
grandfather->_col = RED;
}
else
{
RotateL(grandfather);
//祖父一定是红色,父子谁最后旋到根谁变黑
//单旋父黑,双旋子黑
//单旋爷变子,双旋子变父
parent->_col = BLACK;
grandfather->_col = RED;
}
}
}
}
_root->_col = BLACK;
return true;
}
//左单旋
void RotateL(Node* parent)
{
Node* cur = parent->_right;
Node* curleft = cur->_left;
Node* ppnode = parent->_parent;
//将失衡结点右孩子的左子树链接到失衡结点的右孩子
parent->_right = curleft;
if (curleft)
{
curleft->_parent = parent;
}
//将失衡结点连接到失衡结点右孩子的左孩子位置
parent->_parent = cur;
cur->_left = parent;
//处理父父结点的链接
cur->_parent = ppnode;
if (ppnode == nullptr)//为空代表parent就已经是root了
{
_root = cur;
}
else
{
if (ppnode->_left == parent)//失衡结点是其父节点的左孩子
{
ppnode->_left = cur;
}
else //失衡结点是其父节点的右孩子
{
ppnode->_right = cur;
}
}
}
//右单旋
void RotateR(Node* parent)
{
Node* cur = parent->_left;
Node* curright = cur->_right;
Node* ppnode = parent->_parent;
//将失衡结点左孩子的右子树连接到失衡结点的左孩子位置
parent->_left = curright;
if (curright)
{
curright->_parent = parent;
}
//将失衡结点连接到失衡结点左孩子的右孩子位置
parent->_parent = cur;
cur->_right = parent;
//链接父父结点
cur->_parent = ppnode;
if (ppnode == nullptr)//为空代表parent就已经是root了
{
_root = cur;
}
else
{
if (ppnode->_left == parent)
{
ppnode->_left = cur;
}
else
{
ppnode->_right = cur;
}
}
}
//中序遍历函数
void InOrder()
{
_InOrder(_root); //代替成员函数完成递归
cout << endl; //方便后续观察测试用例
}
//中序遍历子递归函数
void _InOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_InOrder(root->_left); //递归访问左子树
cout << root->_kv.first << " "; //访问根节点
_InOrder(root->_right); //递归访问右子树
}
//验证双红结点和路径黑结点数是否相同函数
bool CheckColour(Node* root, int blacknum, int benchmark)
{
if (root == nullptr)
{
if (benchmark != blacknum)
return false;
return true;
}
if (root->_col == BLACK)
{
++blacknum;
}
if (root->_col == RED && root->_parent && root->_parent->_col == RED)
{
cout << root->_kv.first << "连续红结点" << endl;
return false;
}
return CheckColour(root->_left,blacknum,benchmark)
&& CheckColour(root->_right,blacknum,benchmark);
}
bool IsBalance()
{
return _IsBalance(_root);
}
//RBTree验证函数
bool _IsBalance(Node* root)
{
if (root == nullptr)
return true;
//规则:根节点是黑色
if (root->_col != BLACK)
return false;
//求黑节点基准值
int benchmark = 0;
Node* cur = _root;
while (cur)
{
if (cur->_col == BLACK)
benchmark++;
cur = cur->_left;
}
//规则:不能有连续的红结点,且每条路径黑节点数量相同
return CheckColour(root, 0, benchmark);
}
private:
Node* _root;
};
结语
希望这篇红黑树的实现详解能对大家有所帮助,欢迎大佬们留言或私信与我交流.
学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!