黑红树
使用的平台:vs2015
语言:c++
代码有部分是借鉴的
我是一只菜鸟,在平衡二叉树要旋转的时候总是绕道自己昏头转向,自己都弄不懂那棵树是怎么旋转的,其实我也是不太明白了,但是希望我的代码能够帮助你们解决问题。代码有错误,提前说啦!!
//核心函数: //void rb_right_rotate(rbnode* g) //void rb_left_rotate(rbnode* g) //void rbt_insert_check(rbnode* node) //int rbt_insert(rbtree* &tree, keyType key) //void rbt_delete_check //int is_black //int rbt_delete //左旋和右旋的代码基本相同,只需要更改right和left //插入只有4中情况,而删除有六种 //检查部分需要细心看
#include <iostream>
using namespace std;
#define COLOR_RED 0
#define COLOR_BLACK 1
typedef int keyType;
// 定义而二叉树节点数据结构
struct BinaryTreeNode {
keyType key;
int color;
BinaryTreeNode* parent; // 保存父节点
BinaryTreeNode* left; // left child
BinaryTreeNode* right; // right child
BinaryTreeNode* next;
};
// 定义红黑树的结点
typedef BinaryTreeNode rbnode;
// 定义红黑树
typedef BinaryTreeNode rbtree;
//左旋和右旋的代码基本相同,只需要更改right和left
//插入只有4中情况,而删除有六种
void preorder(rbtree *g);
void inorder(rbtree *g);
void postorder(rbtree *g);
void print(rbtree *g);
//R
void rb_right_rotate(rbnode* g) {
rbnode * p = g->left; //右转,p指向g的left
//交换
keyType k = g->key;
g->key = p->key;
p->key = k;
//g的左节点是g的做节点的左节点
g->left = p->left;
if (NULL != p->left) {//右旋,p的left不能为空
p->left->parent = g;
}
p->left = p->right;
p->right = g->right;
//这个if-else用于将g的父亲节点的left或right点指向p,如果g的父节点为不存在,则树的parent指向p
if (NULL != g->right) {
g->right->parent = p;
}
g->right = p;
}
// L
void rb_left_rotate(rbnode* g) {
rbnode* p = g->right;
keyType k = g->key;
g->key = p->key;
p->key = k;
g->right = p->right;
if (NULL != p->right) {
p->right->parent = g;
}
p->right = p->left;
p->left = g->left;
if (NULL != g->left) {
g->left->parent = p;
}
g->left = p;
}
// 插入后调整
void rbt_insert_check(rbnode* node) {
// CASE 1 : 如果节点等于根节点,则设置节点的颜色为黑色并返回。
if (NULL == node->parent) {
node->color = COLOR_BLACK;
return;
}
// CASE 2 : 当节点的父节点为黑色时,所有功能都已满足,停止检查并返回
if (node->parent->color == COLOR_BLACK) {
return;
}
// 父节点为红色,这意味着祖父节点存在。
rbnode* gf = node->parent->parent;
rbnode* uf = (gf->left == node->parent) ? gf->right : gf->left;
// CASE 3 : 当叔叔节点存在并且它是红时
if (NULL != uf && uf->color == COLOR_RED) {
// 设置父亲和叔叔黑色,设置祖父红色
node->parent->color = COLOR_BLACK;
uf->color = COLOR_BLACK;
gf->color = COLOR_RED;
// 然后重新检查来自CASE 1的祖父节点处的树。
rbt_insert_check(gf);
return;
}
// CASE 4 : 当叔叔是NULL或它的颜色是黑色。
if (node->parent == gf->left) { // 该节点在其祖父的左边
// (a) LL model
if (node == node->parent->left) { //该节点在其父节点的左侧
rb_right_rotate(gf);
}
// (b) LR model
else if (node == node->parent->right) { //该节点在其父节点的右侧
rb_left_rotate(node->parent);
rb_right_rotate(gf);
}
}
else if (node->parent == gf->right) { //该节点在其祖父节点的右侧
// (c) RR model
if (node == node->parent->right) { //该节点在其父节点的右侧
rb_left_rotate(gf);
}
// (d) RL model
else if (node == node->parent->left) { //该节点在其父节点的左侧
rb_right_rotate(node->parent);
rb_left_rotate(gf);
}
}
}
// 插入新的关键字
int rbt_insert(rbtree* &tree, keyType key) {
if (NULL == tree) { // 树是否为空
tree = (rbtree*)malloc((sizeof(rbnode))); //开辟空间
tree->key = key;
tree->color = COLOR_BLACK;//根为黑色
tree->parent = tree->left = tree->right = NULL;
return 1;
}
//寻找插入点
rbnode *n = tree, *p = tree->parent;
while (NULL != n) {
if (key == n->key) { //插入值相同时,不用再插入
return 0;
}
p = n;
n = (key > p->key) ? p->right : p->left; //排序,有利于插入删除
}
// 插入节点
n = (rbtree*)malloc((sizeof(rbnode)));
n->key = key;
n->color = COLOR_RED; //除了根节点外,插入的节点都是红色,当调整完后,方可恢复黑色
n->parent = p;
n->right = n->left = NULL;
((key > p->key) ? p->right : p->left) = n; //判断插入左节点还是右节点
// 调整数
rbt_insert_check(n);
return 1;
}
int is_black(rbnode * node) {
if (node == NULL) return 1;
if (node->color == COLOR_BLACK) return 1;
return 0;
}
//检查删除调整后
void rbt_delete_check(rbnode* p, bool delLeft) {
rbnode * n = delLeft ? p->left : p->right;
// case 1: n 是红
if (NULL != n && n->color == COLOR_RED) {
n->color = COLOR_BLACK;
return;
}
// 其他子树至少一个节点
rbnode * s = delLeft ? p->right : p->left;
rbnode * sl = s->left;
rbnode * sr = s->right;
// case 2 : S 红 , p 左转
if (s->color == COLOR_RED) {
if (delLeft) {
rb_left_rotate(p);
}
else {
rb_right_rotate(p);
}
p = s;
s = delLeft ? sl : sr;
sl = s->left;
sr = s->right;
}
// Other cases : S 黑
// SL 和 SR 黑
if (is_black(sl) && is_black(sr)) {
// case 3 : P红, S SL和 SR 黑
if (!is_black(p)) {
p->color = COLOR_BLACK;
s->color = COLOR_RED;
}
// case 4: P ,S, SL,SR 黑
else {
s->color = COLOR_RED;
if (NULL == p->parent) {
return;
}
delLeft = (p == p->parent->left);
rbt_delete_check(p->parent, delLeft);
}
return;
}
// SL 和 SR 有红色节点
if (delLeft) {
if (is_black(sr)) { // case 5(a) : delLeft 真 ,SR 黑
rb_right_rotate(s);
sr = s->right;
}
rb_left_rotate(p); // case 6(a) : p节点旋转
sr->color = COLOR_BLACK;
}
else {
if (is_black(sl)) { // case 5(b) : delLeft 假 和SL 黑
rb_left_rotate(s);
sl = s->left;
}
rb_right_rotate(p); // case 6(b) : p节点旋转
sl->color = COLOR_BLACK;
}
}
// 删除一个节点
int rbt_delete(rbtree* &tree, keyType key) {
if (NULL == tree) {
return 0;
}
// 寻找节点
rbnode *curr, *temp;
for (curr = tree;;) {
if (key == curr->key) {
break;
}
curr = (key > curr->key) ? curr->right : curr->left;
if (NULL == curr) {
return 0;
}
}
//删除的有两个孩子
if (NULL != curr->left && NULL != curr->right) {
for (temp = curr->left; NULL != temp->right; temp = temp->right) {
}
curr->key = temp->key;
curr = temp;
}
if (NULL == curr->parent) { // 判断是否树的根
tree = (NULL == curr->left) ? curr->right : curr->left;
if (tree != NULL) {
tree->color = COLOR_BLACK;
tree->parent = NULL;
}
free(curr);
return 1;
}
// 删除节点
rbnode* fa = curr->parent;
temp = (NULL == curr->left) ? curr->right : curr->left;
bool delLeft = (fa->left == curr);
if (NULL != temp) {
temp->parent = fa;
}
delLeft ? fa->left = temp : fa->right = temp;
if (curr->color != COLOR_RED) { // adjust after deletion
rbt_delete_check(fa, delLeft);
}
free(curr);
return 1;
}
void preorder(rbnode *g)
{
if (g != NULL)
{
cout << g->key<< " " ;
preorder(g->left);
preorder(g->right);
}
}
void inorder(rbnode *g)
{
if (g != NULL)
{
inorder(g->left);
cout << g->key<<" ";
inorder(g->right);
}
}
void postorder(rbnode *g)
{
if (g != NULL)
{
postorder(g->left);
postorder(g->right);
cout << g->key << " ";
}
}
void print(rbnode *g)
{
//
cout << "先序输出 :";
preorder(g);
cout << endl;
cout << "中序输出 :" ;
inorder(g);
cout << endl;
cout << "后序输出 :";
postorder(g);
cout << endl;
}
int main()
{
rbnode *p=NULL ;
cout << "插入数据:\n" << endl;
for (int i = 0; i <6; i++)
{
cout << i + 1 << endl;
int a;
cin >> a;
rbt_insert(p,a);
print(p);
cout << endl;
}
//cout << "调整后:\n" << endl;
//print(p);
//
cout << "删除数据 :\n" << endl;
for (int i = 0; i <5; i++)
{
cout << i + 1 << endl;
int a;
cin >> a;
rbt_delete(p, a);
print(p);
cout << endl;
}
system("pause");
}