插入操作可能会造成不平衡。
为了使数平衡,AVL树需要rotate操作。那么红黑树怎么弄呢?红黑树需要:
1)recoloring
2) rotate
下面举例说明
假设x是新插入的节点。
1)标准BST树出入,插入后新节点上色为红
2)如果x不为root或者x的父节点不是黑的
a)如果x的叔节点为红:
1.变父节点和叔节点的颜色为黑
2.变爷节点颜色为红
3.爷节点变为新出入的当前结点
b)如果叔节点是黑色的,那么按照AVL树的四种旋转情况rotate
3)如果x为root,将x的颜色变为黑
下面具体讨论叔节点为黑色时候那四种旋转:
Left Left Case:
Left Right Case
Right Right Case
Right Left Case
插入实例:插入10,20,30,15
下面是C语言实现代码:
#include <stdio.h> struct node { int data;// for data part char color;// for color property struct node* left; struct node* right; struct node* parent; }; // leftrotate void leftRotate(struct node** root,struct node* x) { // y store the x's right child struct node* y=x->right; // update x's righit child x->right=y->left; if(x->right!=NULL) { x->right->parent=x; } // update y's parent pointer y->parent=x->parent; // if x's parent is null,make y as root of tree if(x->parent==NULL) { (*root)=y; } else if(x==x->parent->left) { x->parent->left=y; } else { x->parent->right=y; } y->left=x; x->parent=y; } // similar to leftrotate void rightRotae(struct node** root,struct node* x) { struct node* y=x->left; x->left=y->right; if(x->left!=NULL) { x->left->parent=x; } 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; } y->right=x; x->parent=y; } void insertFixup(struct node** root,struct node* z) { while(z!=*root || z->parent->color=='R') { struct node* y; // find uncle and stroe uncle in y if(z->parent=z->parent->parent->left) y=z->parent->parent->right; else y=z->parent->parent->left; // if uncle is red,do following // 1) change color of parent and uncle as black // 2) change color of grandparent as red // 3) move z to grandparent if(y->color=='R') { y->color='B'; z->parent->color='B'; z->parent->parent='R'; z=z->parent->parent; } // uncle is black there is four case else { // left left case do following // 1) swap color parent and grandparent // 2) right rotete grandparent if(z=z->parent->left && z->parent=z->parent->parent->left) { char t=z->parent->color; z->parent->color=z->parent->parent->color; z->parent->parent->color=t; rightRotae(root,z->parent->parent); } // left right case do following // 1) swap color of current and grandparent // 2) left rotate parent // 3) right rotate grandparent if(z=z->parent->right && z->parent=z->parent->parent->left) { char t=z->color; z->color=z->parent->parent->color; z->parent->parent->color=t; leftRotate(root,z->parent); rightRotae(root,z->parent->parent); } // right right case do following // 1) swap color of parent and grandparent // 2) left rotate grandparent if(z=z->parent->right && z->parent=z->parent->parent->right) { \char t=z->parent->color; z->parent->color=z->parent->parent->color; z->parent->parent->color=t; leftRotate(root,z->parent->parent); } // right left case do following // 1) swap color of current and grandparent // 2) right rotate parent // 3) left rotate grandparent if(z=z->parent->left && z->parent=z->parent->parent->right) { char t=z->color; z->color=z->parent->parent->color; z->parent->parent->color=t; rightRotae(root,z->parent); leftRotate(root,z->parent->parent); } } } (*root)->color='B';// keep root always black } void insert(struct node** root,int data) { // allocate memory for new node struct node* z=(struct node*)malloc(sizeof(struct node)); z->data=data; z->left=z->right=z->parent=NULL; // if root is null make z as root if(root==NULL) { z->color='B'; (*root)=z; } else { struct node* pre=NULL; struct node* p=(*root); while(p) { pre=p; if(z->data>p->data) p=p->right; else p=p->left; } z->parent=pre; if(z->data>pre->data) pre->right=z; else pre->left=z; z->color='R'; insertFixup(root,z); } } void inorder(struct node* root) { if(root==NULL) return; inorder(root->left); printf("%d ",root->data); inorder(root->right); } int main(void) { struct node* root=NULL; insert(&root,5); insert(&root,3); insert(&root,7); insert(&root,2); insert(&root,4); insert(&root,6); insert(&root,8); insert(&root,11); inorder(root); printf("Hello World!\n"); return 0; }