/*
项目名称:红黑树练习
实现功能:红黑树的增加和删除
完成时间:2018年4月11日
编辑者:尹浩龙
*/
#include<iostream>
#include<ctime>
using namespace std;
//红黑树节点类
template<typename T>
class TreeNode{
public:
T NodeData;//节点的值
bool Color;//节点的颜色
TreeNode<T>* Letf;//左子树
TreeNode<T>* Right;//右子树
TreeNode<T>* TheLast;//指向父节点
TreeNode(T& NewNodeData);
TreeNode(T& NewNodeData, TreeNode<T>* Letf, TreeNode<T>* Right, TreeNode<T>* TheLast, bool Color);
};
template<typename T>TreeNode<T>::TreeNode(T& NewNodeData) : NodeData(NewNodeData){
Color = true;
Letf = Right = TheLast = NULL;
}
template<typename T>TreeNode<T>::TreeNode(T& NewNodeData, TreeNode<T>* Letf, TreeNode<T>* Right, TreeNode<T>* TheLast, bool Color) : NodeData(NewNodeData), Letf(Letf), Right(Right), TheLast(TheLast), Color(Color){
}
template<typename A, typename B>
class RedBlackTree{
public:
RedBlackTree();//构造函数
void AddNode(const A& Keyword, const B& Data);//增加节点
void DelNode(const A& Keyword);//删除节点
void operator *();
private:
void AntiClockwise(TreeNode<pair<A, B>>* NewNode);//左旋方法
void Clockwise(TreeNode<pair<A, B>>* NewNode);//右旋方法
void AddRepairTree(TreeNode<pair<A, B>>* NewNode);//增加后修复树 使树恢复红黑树的特性
void DelRepairTree(TreeNode<pair<A, B>>* delNode, TreeNode<pair<A, B>>* Current);//删除后修复树 使树恢复红黑树的特性
void SetRed(TreeNode<pair<A, B>>* NewNode);//设置节点为红色
void SetBlack(TreeNode<pair<A, B>>* NewNode);//设置节点为黑色
bool IsRed(TreeNode<pair<A, B>>* NewNode);//设置节点为红色
void ShowRoot();//显示根节点
void ShowSize();//显示树的节点数
void Echo();//打印树
void PutTree(TreeNode<pair<A, B>>* NewNode);//遍历树
void PutNode(TreeNode<pair<A, B>>* NewNode);//打印节点
TreeNode<pair<A, B>>* Root;//根节点指针
int TreeSize;//树的节点
int OutLength;//树的节点
};
template<typename A, typename B>RedBlackTree<A, B>::RedBlackTree(){
Root = NULL;
TreeSize = 0;
OutLength = -1;
}
template<typename A, typename B> void RedBlackTree<A, B>::AddNode(const A& Keyword, const B& Data){
TreeNode<pair<A, B>>* Current = Root;
TreeNode<pair<A, B>>* Previous = NULL;
while (Current != NULL)
{
Previous = Current;
if (Keyword > Current->NodeData.first){
Current = Current->Right;
}
else if (Keyword < Current->NodeData.first){
Current = Current->Letf;
}
else{
Current->NodeData.second;
return;
}
}
TreeNode<pair<A, B>>* NewNodeData = new TreeNode<pair<A, B>>(pair<A, B>(Keyword, Data));
if (Previous == NULL){//树为空直接涂黑插入
NewNodeData->Color = false;
Root = NewNodeData;
}
else{
NewNodeData->TheLast = Previous;
if (Keyword > Previous->NodeData.first){
Previous->Right = NewNodeData;
}
else{
Previous->Letf = NewNodeData;
}
AddRepairTree(NewNodeData);
}
TreeSize++;
}
template<typename A, typename B> void RedBlackTree<A, B>::DelNode(const A& Keyword){
TreeNode<pair<A, B>>* Current = Root, *Father = NULL, *Leader = NULL, *Subordinate = NULL, *Alternate = NULL;
while (Current != NULL&&Current->NodeData.first != Keyword)
{
Father = Current;
if (Keyword > Current->NodeData.first){
Current = Current->Right;
}
else{
Current = Current->Letf;
}
}
if (Current == NULL){
cout << "指定的结点没有找到,无法删除" << endl;
return;
}
if (Current->Letf != NULL&&Current->Right != NULL){//有两个孩子
Leader = Current;
Subordinate = Current->Letf;
while (Subordinate->Right != NULL)//找到替换的节点
{
Leader = Subordinate;
Subordinate = Subordinate->Right;
}
TreeNode<pair<A, B>>* Replace = new TreeNode<pair<A, B>>(Subordinate->NodeData, Current->Letf, Current->Right, Current->TheLast, Current->Color);//用替换节点的值 和删除节点的颜色和关系生成新的节点
if (Father == NULL){//说明删除的是跟节点
Root = Replace;
}
else if (Father->Letf == Current){
Father->Letf = Replace;
}
else if (Father->Right == Current){
Father->Right = Replace;
}
//处理要删除的节点
if (Leader == Current){//如果直接用左子树替换删除节点
if (Subordinate->Letf != NULL){
Alternate = Subordinate->Letf;
Alternate->TheLast = Replace;
}
else{
Alternate = NULL;
}
Replace->Letf = Alternate;
}
else{//替换节点不是删除节点的左子树
if (Subordinate->Letf != NULL){
Alternate = Subordinate->Letf;
Alternate->TheLast = Leader;
}
else{
Alternate = NULL;
}
Leader->Right = Alternate;
}
DelRepairTree(Subordinate, Alternate);
delete Subordinate;
delete Current;
Father = Current = Leader = Subordinate = NULL;
}
else{//如果有一个子树或者没有子树的情况
if (Father == NULL){//说明删除的是跟节点 且只有一个子节点或者没有子节点
if (Current->Letf != NULL){
Alternate = Current->Letf;
Alternate->TheLast = NULL;//根节点的上级指向空
}
else{
Alternate = Current->Right;
if (Alternate != NULL){
Alternate->TheLast = NULL;
}
}
Root = Alternate;
}
else{//删除的不是根节点 且只有一个子节点或者没有子节点
if (Current->Letf != NULL){//有一个左子树
Alternate = Current->Letf;
if (Current == Father->Letf){
Father->Letf = Alternate;
}
else{
Father->Right = Alternate;
}
Alternate->TheLast = Father;//让新连接上的节点指向正确的上级
}
else if (Current->Right != NULL){//有一个右子树
Alternate = Current->Right;
if (Current == Father->Letf){
Father->Letf = Alternate;
}
else{
Father->Right = Alternate;
}
Alternate->TheLast = Father;//让新连接上的节点指向正确的上级
}
else{//没有子树
if (Current == Father->Letf){
Father->Letf = NULL;
}
else{
Father->Right = NULL;
}
Alternate = NULL;
}
DelRepairTree(Current, Alternate);
}
delete Current;
Father = Current = NULL;
}
TreeSize--;
}
template<typename A, typename B> void RedBlackTree<A, B>::operator *(){
OutLength = -1;
cout << endl;
ShowSize();
ShowRoot();
Echo();
}
template<typename A, typename B> void RedBlackTree<A, B>::AntiClockwise(TreeNode<pair<A, B>>* NewNode){//左旋
/*
A <-传进来为A 转换后: C
/ \ / \
B C A E
/ \ / \
D E B D
*/
if (NewNode != NULL) {
TreeNode<pair<A, B>>* Temp = NewNode->Right;//用一个指针指向C
//修改子树所属
NewNode->Right = Temp->Letf;//把C的左子树变成A的右子树
if (Temp->Letf != NULL){//如果D为空,A的右子树为空,不需要再让D连接A,如果D不为空就把D的向上指针指向A
Temp->Letf->TheLast = NewNode;
}
//修改外联节点
Temp->TheLast = NewNode->TheLast;//C的【向上指针】指向A的【向上指针】指向,为C替代A做准备
if (NewNode->TheLast == NULL){//如果A的【向上指针】等于空说明A是红黑树的根节点
Root = Temp;//当A是根节点时需要把根节点移动到C 让C成为新的根节点
}
else if (NewNode->TheLast->Letf == NewNode)//A节点是上级节点的左子树就让C成为A上级的左子树
NewNode->TheLast->Letf = Temp;
else
NewNode->TheLast->Right = Temp;
Temp->Letf = NewNode;//让A成为C的左子树
NewNode->TheLast = Temp;//连接A到C
}
}
template<typename A, typename B> void RedBlackTree<A, B>::Clockwise(TreeNode<pair<A, B>>* NewNode){//右旋
/*
A <-传递进来A 转换后: B
/ \ / \
B C D A
/ \ / \
D E E C
*/
if (NewNode != NULL) {
TreeNode<pair<A, B>>* Temp = NewNode->Letf;//用一个指针指向B
//修改子树所属
if (Temp->Right != NULL){//如果E为空,A的左子树为空,不需要再让E连接A,如果E不为空就把E的向上指针指向A
NewNode->Letf = Temp->Right;//把C的左子树变成A的右子树
Temp->Right->TheLast = NewNode;
}
else{
NewNode->Letf = NULL;
}
//修改外联节点
Temp->TheLast = NewNode->TheLast;//B的【向上指针】指向A的【向上指针】指向,为B替代A做准备
if (NewNode->TheLast == NULL){//如果A的【向上指针】等于空说明A是红黑树的根节点
Root = Temp;//当A是根节点时需要把根节点移动到C 让C成为新的根节点
Temp->Color = false;
}
else if (NewNode->TheLast->Letf == NewNode)//A节点是上级节点的左子树就让C成为A上级的左子树
NewNode->TheLast->Letf = Temp;
else
NewNode->TheLast->Right = Temp;
Temp->Right = NewNode;//让A成为C的右子树
NewNode->TheLast = Temp;//连接A到C
}
}
template<typename A, typename B> void RedBlackTree<A, B>::AddRepairTree(TreeNode<pair<A, B>>* NewNode){
TreeNode<pair<A, B>>*Grandpa = NULL, *Pedar = NULL, *Uncle = NULL, *Temp = NULL;
while (NewNode->TheLast != NULL&&NewNode->TheLast->Color)//如果NewNNewNode->TheLast==NULL说明到达根节点或者父节点不是红色不用继续处理
{
Pedar = NewNode->TheLast;
Grandpa = Pedar->TheLast;
if (Pedar == Grandpa->Letf){//说明父亲在爷爷的左侧
Uncle = Grandpa->Right;//找到叔叔节点
if (Uncle != NULL&& Uncle->Color){//如果叔叔是红色
SetBlack(Uncle);//把叔叔和父亲都改为黑色 爷爷改为红色
SetBlack(Pedar);
SetRed(Grandpa);
NewNode = Grandpa;
continue;
}
else{
if (NewNode == Pedar->Right){
//如果新节点在父亲右侧 父亲在爷爷左侧 就旋转为左侧处理
//此处判断不能写成赋值 写成赋值后程序不会报错 根节点不会变化 红黑树就不成立了
AntiClockwise(Pedar);
NewNode = Pedar;
continue;
}
SetBlack(Pedar);
SetRed(Grandpa);
Clockwise(Grandpa);
NewNode = Pedar;
}
}
else{//父亲在爷爷的右侧
Uncle = Grandpa->Letf;//找到叔叔节点
if (Uncle != NULL&& Uncle->Color){//如果叔叔是红色
SetBlack(Uncle);//把叔叔和父亲都改为黑色 爷爷改为红色
SetBlack(Pedar);
SetRed(Grandpa);
NewNode = Grandpa;
continue;
}
else{
if (NewNode == Pedar->Letf){
Clockwise(Pedar);
NewNode = Pedar;
continue;
}
SetBlack(Pedar);
SetRed(Grandpa);
AntiClockwise(Grandpa);
NewNode = Pedar;
}
}
}
SetBlack(Root);
}
template<typename A, typename B> void RedBlackTree<A, B>::DelRepairTree(TreeNode<pair<A, B>>* delNode, TreeNode<pair<A, B>>* Current){
TreeNode<pair<A, B>>* Pedar = NULL, *Brother = NULL;
if (!IsRed(delNode)){
Pedar = delNode->TheLast;
while (Current != Root && (Current == NULL || !IsRed(Current))){
if (Current == Pedar->Letf) {
Brother = Pedar->Right;
if (Brother != NULL&&IsRed(Brother)){
SetBlack(Brother);
SetRed(Pedar);
AntiClockwise(Pedar);
Brother = Pedar->Right;
}
if ((Brother->Letf == NULL || !IsRed(Brother->Letf)) && (Brother->Right == NULL || !IsRed(Brother->Right))){
//兄弟节点没有子树 或者子树都为黑的情况
SetRed(Brother);
Current = Pedar;
Pedar = Pedar->TheLast;
}
else{
if (Brother->Right == NULL || !IsRed(Brother->Right)){
if (Brother->Letf != NULL)SetBlack(Brother->Letf);
SetRed(Brother);
Clockwise(Brother);
Brother = Pedar->Right;
}
Brother->Color = Pedar->Color;
SetBlack(Current);
if (Brother->Right != NULL)SetBlack(Brother->Right);
AntiClockwise(Pedar);
break;
}
}
else { // same as above, with _M_right <-> _M_left.
Brother = Current->Letf;
if (IsRed(Brother)) {
SetBlack(Brother);
SetRed(Pedar);
Clockwise(Pedar);
Brother = Pedar->Letf;
}
if ((Brother->Right == NULL || !IsRed(Brother->Right)) && (Brother->Letf == NULL || !IsRed(Brother->Letf))){
SetRed(Brother);
Current = Pedar;
Pedar = Pedar->TheLast;
}
else {
if (Brother->Letf == NULL || !IsRed(Brother->Letf)){
if (Brother->Right != NULL)SetBlack(Brother->Right);
SetRed(Brother);
AntiClockwise(Brother);
Brother = Pedar->Letf;
}
Brother->Color = Pedar->Color;
SetBlack(Pedar);
if (Brother->Letf != NULL)SetBlack(Brother->Letf);
Clockwise(Pedar);
break;
}
}
}
SetBlack(Current);
}
}
template<typename A, typename B> void RedBlackTree<A, B>::SetRed(TreeNode<pair<A, B>>* NewNode){
NewNode->Color = true;
}
template<typename A, typename B> void RedBlackTree<A, B>::SetBlack(TreeNode<pair<A, B>>* NewNode){
NewNode->Color = false;
}
template<typename A, typename B> bool RedBlackTree<A, B>::IsRed(TreeNode<pair<A, B>>* NewNode){
return NewNode->Color;
}
template<typename A, typename B> void RedBlackTree<A, B>::ShowRoot(){
cout << "根节点是:"; PutNode(Root);
}
template<typename A, typename B> void RedBlackTree<A, B>::ShowSize(){
cout << "当前树中有节点:" << TreeSize << "个。" << endl;
}
template<typename A, typename B> void RedBlackTree<A, B>::Echo(){
cout << "红黑树节点列表:" << endl;
PutTree(Root); cout << endl;
}
template<typename A, typename B> void RedBlackTree<A, B>::PutTree(TreeNode<pair<A, B>>* NewNode){
if (NewNode != NULL){
PutTree(NewNode->Letf);
PutNode(NewNode);
PutTree(NewNode->Right);
}
}
template<typename A, typename B> void RedBlackTree<A, B>::PutNode(TreeNode<pair<A, B>>* NewNode){
cout << "\t[" << NewNode->NodeData.first << "|" << NewNode->Color << "|" << NewNode->NodeData.second << "]";
OutLength++;
if (OutLength % 3 == 0){
cout << endl;
}
}
int main(){
srand((unsigned)time(NULL));
RedBlackTree<int, int> myTree;
for (int i = 1; i < 27; i++)
myTree.AddNode(i, rand() % 1000 + 1000);
*myTree;
myTree.DelNode(1);
*myTree;
myTree.DelNode(9);
*myTree;
system("pause");
return 0;
}
红黑树的增加与删除(完整源码版)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.