// 模板_建树.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<queue>
#include<iomanip>
#include<Windows.h>
#include<iostream>
#include<string>
#include<ctime>
using namespace std;
//红黑树
enum colortype { RED, BLACK };
struct node {
int data;
colortype color;
node*L, *R, *F;
} *NIL, *root;
void show_tree();
void ini() {
NIL = new node;
NIL->color = BLACK;
NIL->L = NULL;
NIL->R = NULL;
NIL->F = NULL;
root = NIL;
}
void RR(node*cur) {
node*it, *itF, *itL, *itLR;
it = cur;
itF = cur->F;
itL = cur->L;
itLR = cur->L->R;
it->L = itLR;
itLR->F = it;
it->F = itL;
itL->R = it;
itL->F = itF;
if (root == it) root = itL;
else it == itF->L ? itF->L = itL : itF->R = itL;
}
void LR(node*cur) {
node*it, *itR, *itF, *itRL;
it = cur;
itR = cur->R;
itF = cur->F;
itRL = cur->R->L;
it->R = itRL;
itRL->F = it;
it->F = itR;
itR->L = it;
itR->F = itF;
if (root == it) root = itR;
else it == itF->R ? itF->R = itR : itF->L = itR;
}
void ins_adj(node*cur) {
node*father = cur->F;
node*grand = father->F;
node*uncle = father == grand->L ? grand->R : grand->L;
/*
-----gB-----
----fR---- ----uR----
cR ? ? ?
? ?
move father's and uncle's RED up then may be grandfather'father is RED,
if that ,father will not be the root ,we think grandfather is the new cur;
-----gR-----
----fB---- ----uB----
cR ? ? ?
? ?
*/
if (uncle->color == RED) {
father->color = BLACK;
uncle->color = BLACK;
grand->color = RED;
if (grand == root)grand->color = BLACK;
else if (grand->F->color == RED)ins_adj(grand);
}
/*there are 4 case and there is only show one of them
-----gB-----
----fR---- ----uB----
? cR ? ?
? ?
rote fR and then we can think father is the new cur;
-----gB-----
----fR---- ----uB----
cR ? ? ?
? ?
rote grandfather and change the color between father and grandfather ,end;
-----fB-----
cR ----gB----
? ? ? uB
? ?
*/
else {
///
if (father == grand->L) {
if (cur == father->R) {
LR(father);
father = cur;
cur = cur->L;
}
father->color = BLACK;
grand->color = RED;
RR(grand);
}
else {
if (cur == father->L) {
RR(father);
father = cur;
cur = cur->R;
}
father->color = BLACK;
grand->color = RED;
LR(grand);
}
///
}
}
void del_adj(node*cur) {
if (cur == root)return;
if (cur->color == RED) {
// the another black become the real black;
cur->color = BLACK;
return;
}
//now cur is black and it have another black
/*
----f?----
cB ?
? ?
*/
node*father = cur->F;
node*broder = father->L == cur ? father->R : father->L;//cur_tree
/*
----fB----
cB bR
? ? ? ?
rote fahter
----bB---
fB ?
cB ?
? ?
*/
if (broder->color == RED) {//a way to give a black broder to cur
father->color = RED;
broder->color = BLACK;
if (broder == father->L)RR(father), broder = father->L;
else LR(father), broder = father->R;
}
//now broder is black,but we don't know father's color,we don't care that
/*
----f?----
cB bB
? ? B B
move BLACK between cur and broder up,we can think father is the new one have the another black;
----f?----
cB bR
? ? B B
*/
if (broder->L->color == BLACK && broder->R->color == BLACK) {//move another black to father
broder->color = RED;
cur = father;
del_adj(cur);
return;
}
/*there are 4 case and only show one of them
----f?------
cB --bB-
? ? R B
? ? ? ?
make the broder'special child is RED;
-----f?------
cB --B-
? ? ? bR
? B
? ?
we only care this part
-----f?------
cB --B-
? ? ? bR
? ?
change it to this ,don't care father's color and give it to the new one who stand in father's place;
-----B?------
fB bB
cB ? ? ?
? ?
ok!!!!!!!!!!!
*/
if (cur == father->L) {
if (broder->R->color == BLACK) {//then broder->L->color==RED
broder->color = RED;
broder->L->color = BLACK;
RR(broder);
broder = broder->F;
}
//now broder->R->color==RED and broder is black;move another black to father
broder->R->color = BLACK;
broder->color = father->color;
father->color = BLACK;
LR(father);
}
else {
if (broder->L->color == BLACK) {
broder->color = RED;
broder->R->color = BLACK;
LR(broder);
broder = broder->F;
}
broder->L->color = BLACK;
broder->color = father->color;
father->color = BLACK;
RR(father);
}
}
node*find(int x, node*cur = root) {
if (cur == NULL) {
cout << "couldn't find " << x << endl;
show_tree();
system("pause");
return NULL;
}
if (x > cur->data)return find(x, cur->R);
else if (x < cur->data) return find(x, cur->L);
else if (x == cur->data)return cur;
}
void insert(int x, node*&cur = root, node*fa = NULL) {
if (cur == NIL) {
cur = new node;
cur->data = x;
cur->color = RED;
cur->L = NIL;
cur->R = NIL;
cur->F = fa;
if (root == cur)cur->color = BLACK;
else if (cur->F->color == RED)ins_adj(cur);
}
else if (x > cur->data)insert(x, cur->R, cur);
else insert(x, cur->L, cur);
}
void del(node*wtd) {
if (wtd == NULL) {
cout << "delete error" << endl;
return;
}
node*td = wtd;
//find one to replace wtd and then delete it;
if (td->L != NIL && td->R != NIL) {
td = td->L;
while (td->R != NIL)td = td->R;
wtd->data = td->data;
}
if (td->F == NULL) {
root = td->L != NIL ? td->L : td->R;
root->F = NULL;
root->color = BLACK;
delete td;
return;
}
node*father = td->F;
node*broder = father->L == td ? father->R : father->L;
node*child = td->L != NIL ? td->L : td->R;
if (td == father->L) father->L = child;
else father->R = child;
child->F = father;
if (td->color == BLACK)del_adj(child);//Now there is another black in child
delete td;
}
void clear(node*cur = root) {
if (cur == NIL)return;
if (cur->L != NIL)clear(cur->L);
if (cur->R != NIL)clear(cur->R);
delete cur;
cur = NIL;
}
void mid(node*cur = root) {
if (cur->L != NIL)mid(cur->L);
cout << cur->data << " ";
if (cur->R != NIL)mid(cur->R);
}
void front(node*cur = root) {
cout << cur->data << " ";
if (cur->L != NIL)mid(cur->L);
if (cur->R != NIL)mid(cur->R);
}
int main()
{
srand(time(NULL));
ini();
int a[20];
for (int i = 0; i < 20; i++)
a[i] = 4*i+10;
random_shuffle(a, a + 20);
for (int i = 0; i < 20; i++)cout << "insert " << a[i] << endl, insert(a[i]),show_tree();
string str;
int key;
while (cin >> str >> key) {
if (str == "delete")del(find(key));
else if (str == "insert")insert(key);
else { cout << "cin error" << endl; continue; }
show_tree();
cout << "中序"; mid(); cout << endl;
cout << "先序"; front(); cout << endl;
cout << endl;
}
}
void show_tree() {
//调一下控制台便,可以查看深度小于7的树
if (root == NIL) {
cout << "error no tree " << endl;
return;
}
queue<node*>a, b;
a.push(root);
int t = 7;
for (int i = 0; i < t;) {
int d = (1 << (t - i)) - 1;
if (a.front() == NULL)b.push(NULL), b.push(NULL);
else {
if (a.front()->L != NIL)b.push(a.front()->L);
else b.push(NULL);
if (a.front()->R != NIL)b.push(a.front()->R);
else b.push(NULL);
}
if (a.front() != NULL) {
if (a.front()->color == RED)SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED);
else SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN);
{
cout.fill(' ');
cout << setw(d - d / 2) << "";
cout.fill('-');
cout << setw(d / 2) << "" << setw(2) << a.front()->data << setw(d / 2) << "";
cout.fill(' ');
cout << setw(d - d / 2) << "";
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}
else cout << setw(2 * d + 2) << "";
a.pop();
if (a.empty()) {
while (!b.empty()) {
a.push(b.front());
b.pop();
}
i++;
cout << endl;
}
}
cout << endl;
}