将红黑树15种情况压缩成插入3种,删除两种情况。插入看祖父节点,删除看父节点,同时合并度为1,以及度为0的插入与删除的调整,度为2的找前驱和后继,我写的找前驱,同时对处理失衡时采用红色上浮的一个调整策略(当然黑色下沉也是可以的),同时巧妙的处理了双黑情况。这里的空地址我采用了一个虚拟空节点,这样就不会造成程序崩溃了,详情请看代码
#include
#include
#include
using namespace std;
struct node {
int key, color;// color = 0 red, 1 black,2 double black;
node* l, * r;
};
node __NIL;
#define NIL (&__NIL)
void init_NIL() {
NIL->key = 0;
NIL->l = NIL->r = NULL;
NIL->color = 1;
return;
}
node* get(int key) {
node* p = (node*)malloc(sizeof(node));
p->key = key;
p->color = 0;
p->l = p->r = NIL;
return p;
}
int has_red_child(node* root) {
return root->l->color == 0 || root->r->color == 0;
}
node* left_rotate(node* root) {
node* new_temp = root->r;
root->r = new_temp->l;
new_temp->l = root;
return new_temp;
}
node* right_rotate(node* root) {
node* new_temp = root->l;
root->l = new_temp->r;
new_temp->r = root;
return new_temp;
}
const string cnt[5] = {
“1 : change_color”,
“2: LL”,
“2 : LR”,
“2: RR”,
“2: RL”
};
node* insert_maintain(node* root) {
if (!has_red_child(root))return root;
if (!(root->l->color == 0 && has_red_child(root->l)) && !(root->r->color == 0 && has_red_child(root->r)))return root;
//rotate
int type = 0;
if (root->r->color == 1) {
if (root->l->r->color == 0) {
root->l = left_rotate(root->l);
type++;
}
type++;
root = right_rotate(root);
}
else if (root->l->color == 1) {
type = 2;
if (root->r->l->color == 0) {
root->r = right_rotate(root->r);
type++;
}
type++;
root = left_rotate(root);
}
root->color = 0;
root->l->color = root->r->color = 1;
return root;
}
node* __insert(node* root, int key) {
if (root == NIL)return get(key);
if (root->key == key)return root;
if (root->key > key)root->l = __insert(root->l, key);
else root->r = __insert(root->r, key);
return insert_maintain(root);
}
node* insert(node* root, int key) {
root = __insert(root, key);
root->color = 1;
return root;
}
const char* erase_maintain_type_str[] = {
“red 1(right): change color”,
“red 2(left) : change color”,
“black 1 : no red child”,
“black 2 : LL”,
“black 2: LR”,
“black 2: RR”,
“black 2: Rl”,
};
node* erase_maintain(node* root) {
if (root->l->color != 2 && root->r->color != 2)return root;
int type = 0;
if (has_red_child(root)) {
root->color = 0;
if (root->l->color == 0)root = right_rotate(root);
else root = left_rotate(root), type = 1;
root->color = 1;
if (type)root->l = erase_maintain(root->l);
return root;
}
if (root->l->color == 1 && !(has_red_child(root->l)) || root->r->color == 1 && !(has_red_child(root->r))) {
type = 2;
root->l->color -= 1;
root->color += 1;
root->r->color -= 1;
return root;
}
type = 2;
if (root->l->color == 1) {
if (root->l->l->color != 0) {
type += 1;
root->l = left_rotate(root->l);
}
type += 1;
root->r->color = 1;
root->l->color = root->color;
root = right_rotate(root);
}
else {
type = 3;
if (root->r->r->color != 0) {
type += 1;
root->r = right_rotate(root->r);
}
type += 1;
root->l->color = 1;
root->r->color = root->color;
root = left_rotate(root);
}
root->l->color = root->r->color = 1;
return root;
}
node* __erase(node* root, int key) {
if (root == NIL)return root;
if (root->key < key)root->r = __erase(root->r,key);
else if (root->key > key)root->l = __erase(root->l,key);
else {
if (root->l == NIL || root->r == NIL) {
node* temp = root->l == NIL ? root->r : root->l;
temp->color = root->color;
free(root);
return temp;
}
else {
node* temp = root->l;
while (temp->r != NIL)temp = temp->r;
root->key = temp->key;
root->l = __erase(root->l, temp->key);
}
}
return erase_maintain(root);
}
node erase(node root, int key) {
root = __erase(root, key);
root->color = 1;
return root;
}
void clear(node* root) {
if (root == NIL)return;
clear(root->l);
clear(root->r);
free(root);
}
void print_node(node* root) {
printf("%d %d %d %d\n", root->key, root->color, root->l->key, root->r->key);
}
void output(node* root) {
if (root == NIL)return;
output(root->l);
print_node(root);
output(root->r);
return;
}
int main() {
init_NIL();
node* root = NIL;
// 输入1 插入值 2 删除值 3 中序遍历打印
int key,k;
while (cin>>k>>key) {
if(k == 1)
root = insert(root, key);
if(k == 2)
root = erase(root, key);
if (k == 3) {
output(root);
}
}
clear(root);
return 0;
}