之前的作业,代码中还有需要完善的地方,如内存管理等,先贴上实现代码,后续会对红黑树的具体实现进行分析。
// 红黑树.cpp : Defines the entry point for the console application.
// author: sqxu
#include "stdafx.h"
#include <iostream>
using namespace std;
const int red=0;
const int black=1;
typedef struct rbtree
{
int key; //关键字
int color; //颜色
struct rbtree * parent; //指向父结点的指针
struct rbtree * left; //指向左孩子的指针
struct rbtree * right; //指向右孩子的指针
}RBT; //定义结构体RBT
void leftRotate(RBT ** root, RBT * x); //左旋函数
void rightRotate(RBT ** root, RBT * x); //右旋函数
void rbInsertFixUp(RBT ** root, RBT * z); //插入后的调整
void rbInsert(RBT ** root, RBT * z); //插入操作
void print(RBT * x); //打印一个结点
void rbprint(RBT ** root); //打印一棵树
int main()
{
RBT ** root; //root指向根结点
root = (RBT**)malloc(sizeof(RBT*));
*root = NULL; //初始时树为空
const int MAX = 100; //定义数组的最大长度
int arrays[MAX];
int n;
cout<<"请输入数组的长度:"<<endl;
cin>>n;
cout<<"请输入数据:"<<endl;
for(int i=0;i<n;i++) //输入数组元素
{
cin>>arrays[i];
}
for(int i=0; i<n; i++)
{
RBT * z = (RBT*)malloc(sizeof(RBT)); //定义一个指向新结点的指针z
z->key = arrays[i]; //结点z的key值指向数组中的元素
rbInsert(root, z); //将z指向的值插入到树中
}
cout<<"红黑树为:"<<endl;
rbprint(root); //打印红黑树
return 0;
}
void leftRotate(RBT ** root, RBT * x) //左旋函数
{
RBT* y;
y = x -> right;//step1,确定y
if(x -> right != NULL && y != NULL)
x -> right = y -> left;
if(y != NULL && y -> left != NULL)
y -> left -> parent = x; //step2,y的左孩子与x的右孩子连接
if(y != NULL)
y -> parent = x -> parent;
if(x -> parent == NULL)
* root = y;
else
{
if(x == x -> parent -> left)
x -> parent -> left = y;
else
x -> parent-> right = y;
} //step3,x的父结点作为y的父结点
if(y != NULL)
{
y -> left = x;
x -> parent = y; //step4,x与y交换
}
}
void rightRotate(RBT ** root, RBT * x) //右旋函数
{
RBT* y;
y = x -> left; //step1,确定y的位置
if(x -> left != NULL && y != NULL)
x -> left = y -> right;
if(y -> right != NULL && y -> left != NULL)
y -> right -> parent = x; //step2,将y的右孩子变成x的左孩子
if(y != NULL)
y -> parent = x -> parent;
if(x -> parent == NULL)
* root = y;
else
{
if(x == x -> parent -> left)
x -> parent -> left = y;
else
x -> parent -> right = y;
} //step3,x的父结点作为y的父结点
if(y != NULL)
{
y -> right = x;
x -> parent = y;
} //step4,x与y交换
}
void rbInsert(RBT ** root, RBT * z) //插入函数
{
RBT * y, * x; //定义指针x和y,x指向根结点,y指向空结点
y = NULL;
x = * root;
while(x != NULL)
{
y = x;
if((z -> key) < (x -> key))
x = x -> left;
else
x = x -> right;
}
z -> parent = y;
if(y == NULL)
* root = z;
else
{
if((z -> key)<(y -> key))
y -> left = z;
else
y -> right = z;
} //确定插入元素的位置
z -> left = NULL;
z -> right = NULL;
z -> color = red; //对插入点进行初始化
rbInsertFixUp(root,z); //调用调整函数
}
void rbInsertFixUp(RBT ** root, RBT * z)
{
if(*root != NULL)
{
RBT * y;
while(z -> parent != NULL && z -> parent -> color == red) //只有当z的父结点为red时才有调整的必要
{
if(z -> parent -> parent -> left == z -> parent) //z的父结点是祖父结点的左孩子
{
y = z -> parent -> parent -> right; //定义y为z的叔叔结点
if(y != NULL && y -> color == red)//case1,叔叔结点y不为空且color为red
{
z -> parent -> color = black;
y -> color = black;
z -> parent -> parent -> color = red;
z = z -> parent -> parent; //调整颜色后定义z的祖父结点为新的z
}
else //case2、case3
{
if(z == z -> parent -> right) //case2,z是其父结点的右孩子
{
z = z -> parent;
leftRotate(root,z);
} //case2转换成case3
z -> parent -> color = black;
z -> parent -> parent->color = red;
rightRotate(root,z -> parent -> parent);
}
}
else //z的父结点为祖父结点的右孩子,操作同上
{
y = z -> parent -> parent -> left;
if(y != NULL && y -> color == red)
{
z -> parent -> color = black;
y -> color = black;
z -> parent -> parent -> color = red;
z = z -> parent -> parent;
}
else
{
if(z == z -> parent -> left)
{
z = z -> parent;
rightRotate(root,z);
}
z -> parent -> color = black;
z -> parent -> parent -> color = red;
leftRotate(root,z -> parent -> parent);
}
}
}
(*root)->color = black;
}
}
void print(RBT * x)
{
if(x !=NULL)
{
cout<<"key: "<<x -> key<<'\t'; //打印关键字
if(x -> parent != NULL) //打印父结点
cout<<" parent: "<< x -> parent -> key<<'\t';
else
cout<<" parent: nil"<<'\t';
if(x -> left != NULL) //打印左孩子
cout<<" left: "<<x -> left -> key<<'\t';
else
cout<<" left: nil"<<'\t';
if(x -> right != NULL) //打印右孩子
cout<<" right: "<<x -> right -> key<<'\t';
else
cout<<" right: nil"<<'\t';
if(x -> color == red) //打印颜色
cout<<" color: red"<<endl;
else
cout<<" color: black"<<endl;
}
}
void rbprint(RBT ** root) //打印红黑树
{
if(*root != NULL)
{
print(*root);
rbprint(&((*root)->left));//采用引用的方式递归调用
rbprint(&((*root)->right));
}
}