红黑树

来源:互联网 发布:mac自动整理文件夹 编辑:程序博客网 时间:2024/06/10 03:22

关于红黑树的故事:

如果被删的是红结点,那么没影响

如果是黑结点,那么它死了,但它留下了它黑色的魂来支撑整个红黑树的结构,让这棵树暂时看起来合法。但毕竟这个魂是多余的,它需要附着在其它节点上,以至于有的点成了“双重黑”,于是需要不断地把这个黑魂往上挤,其间这个魂都是存在的,也就是说这棵树一直被你假装成合法的,直到这个黑魂被你挤出这棵树那么就真的合法了。

以下是我个人的理解,我觉得还是将x路看作少了一个黑点来理解更容易一些。

删除部分:纸质版红黑树Delete






代码:

#include<iostream>#include<string>using namespace std;#define black 1#define red 0struct node{node* p;node* left;node* right;int key;bool color;node(){}node(node* init,int k):p(init),left(init),right(init),key(k),color(black){}};struct tree{node* root;node* nil;tree(){root=new node(NULL,-1),nil=root;}};node* tree_Minimum(tree* t,node *x) //找比x小的值,一直往左遍历{  while(x->left != t->nil)          x = x->left;      return x;  } node* search(tree* t,int key){node* x=t->root;while(x!=t->nil && x->key !=key){if(key < x->key)x=x->left;else x=x->right;}if(x==t->nil)//找不到{cout<<"Search Failed!"<<endl;exit(1);//暴力关闭,I like it,但是不和谐}return x;}void left_rotate(tree* t,node* x){node* y=x->right;x->right=y->left;if(y->left!=t->nil)y->left->p=x;y->p=x->p;if(x->p==t->nil)t->root=y;else if(x==x->p->left)x->p->left=y;else x->p->right=y;x->p=y;y->left=x;}void right_rotate(tree* t,node* x){node* y=x->left;x->left=y->right;if(y->right!=t->nil)y->right->p=x;y->p=x->p;if(x->p==t->nil)t->root=y;else if(x==x->p->right)x->p->right=y;else x->p->left=y;x->p=y;y->right=x;}void rb_insert_fixup(tree* t,node* z){node* y;while(z->p->color==red){if(z->p==z->p->p->left){y=z->p->p->right;if(y->color==red){z->p->color=black;y->color=black;y->p->color=red;z=z->p->p;}else {if(z==z->p->right){z=z->p;left_rotate(t,z);}z->p->color=black;z->p->p->color=red;right_rotate(t,z->p->p);}}else {y=z->p->p->left;if(y->color==red){z->p->color=black;y->color=black;y->p->color=red;z=z->p->p;}else {if(z==z->p->left){z=z->p;right_rotate(t,z);}z->p->color=black;z->p->p->color=red;left_rotate(t,z->p->p);}}}t->root->color=black;}void rb_insert(tree* t,node* z){node* y=t->nil;node*x=t->root;while(x!=t->nil){y=x;if(z->key < x->key)x=x->left;else x=x->right;}z->p=y;if(y==t->nil)t->root=z;else if(z->key < y->key)y->left=z;else y->right=z;z->left=t->nil;z->right=t->nil;z->color=red;rb_insert_fixup(t,z);}void print(tree* t,node* x){if(x->key==-1)//空树直接返回,因为空树的根初始为-1return ;else if(x!=t->nil)//中序遍历{print(t,x->left);cout<<x->key<<' '<<x->color<<endl;print(t,x->right);}}void rb_delete_fixup(tree* t,node* x){node* w;while(x !=t->root && x->color==black){if(x==x->p->left)//这里是==,调试写成了=,慎重{w=x->p->right;//case 1:if(w->color==red)//case 1:x的兄弟结点w为红,操作目的:将w转化为黑,转化为case 2,3,4{x->p->color=red;w->color=black;left_rotate(t,x->p);w=x->p->right;}//case 2:if(w->left->color==black && w->right->color==black )//case 2:兄弟结点w为黑且w的左右孩子均为黑,{//操作目的:使x子树和w子树平衡,因为一开始x路比其它路少1个黑色点,现在将w的黑色涂去,换成红色,那么x路和w路平衡,但是,x.p路又比其它路少1个黑色点,因为左右子树都少了一个黑色点w->color=red; x=x->p; //于是需要将额外的黑色点向上附着在x->p身上形成双重黑,继续向上:如果新双重点原来是红色,那么直接涂黑,done,否则继续}else{//case 3:if(w->right->color==black)//case 3:w为黑,w->right为黑,w->left为红,操作目的:转化为case 4{w->color=red;w->left->color=black;right_rotate(t,w);w=x->p->right;}//case 4:w->color=x->p->color;//case 4:可以付储行动的情况,x路原本少1黑色,现在通过以下操作(exchange_color 和left_rotate),可以将x路黑高加1而其它路的黑高保持不变,则整棵树平衡,算法结束x->p->color=black;w->right->color=black;left_rotate(t,x->p);x=t->root;//注意不要写漏,这里为了退出循环}}else{//与上面对称,将left-right对调即可w=x->p->left;if(w->color==red){w->color=black;x->p->color=red;right_rotate(t,x->p);w=x->p->left;}if(w->left->color==black && w->right->color==black){w->color=red;x=x->p;}else {if(w->left->color==black){w->color=red;w->right->color=black;right_rotate(t,w);w=x->p->left;}w->color=x->p->color;x->p->color=black;w->left->color=black;right_rotate(t,x->p);x=t->root;x=t->root;}}}x->color=black;}node* rb_delete(tree* t,node* z){node* y;//指向实际要删的结点node* x;//指向y的下一个结点if(z->left ==t->nil || z->right==t->nil)//1.如果存在其中一个子树为空,则删除的是zy=z;//2.if(z->left !=t->nil && z->right!=t->nil)后继==z->right子树的最小值else y=tree_Minimum(t,z->right);//否则删除z的后继,由上面可知y最多只有一个子树:如果由1而来,存在一个子树为空,如果由2而来,后继必没有左子树if(y->left==t->nil)x=y->right;//x指向y的下一个结点else x=y->left;//***********transplant(tree* t,node* y,node* x)的代码:将x子树移植到y节点x->p=y->p;if(y->p==t->nil)t->root=x;else if(y==y->p->left)y->p->left=x;else y->p->right=x;//调整指针,删掉y:将y结点去除,将y->key赋给z->key//****************************************************if(y!=z)z->key = y->key;if(y->color==black)//如果为红,删掉一个红结点,无影响,如果为黑,调用rb_delete_fixup调整rb_delete_fixup(t,x);return y;//返回指针,避免内存泄漏}void main(){int S[]={7,2,11,1,5,8,14,4,15};int len=sizeof(S)/sizeof(S[0]);node* y;tree* t=new tree();for(int i=0;i<len;i++){y=new node(t->nil,S[i]);rb_insert(t,y);}print(t,t->root);rb_delete(t,t->root); cout<<endl;print(t,t->root);}
结果:



原创粉丝点击