红黑树(RED-BLACK TREE)的插入和删除
2014-07-12 16:06
507 查看
红黑树的插入和删除会需要用到旋转和颜色翻转。颜色翻转和旋转的主要目的是为了保证红黑树的5个性质,插入最直接来讲可能会导致根结点是红色(树为空),红色结点的子结点为红色,这是需要进行红黑调整以及子树翻转。删除最直接的结果就是删除了黑色结点,那么导致沿着该结点的路径上的黑色结点数目发生变化,此时需要翻转颜色和旋转子树来平衡。
红黑树的左旋和右旋
图1 左旋和右旋示意图
左旋的伪代码:
代码很好理解,不用赘述,右旋可以参照给出,很简单。
红黑树的插入情况可以修改二叉查找树的插入函数完成插入,同理删除情况也是如此。
插入可能导致的情形及应对的策略有下面几种:
图2 插入的情形(一侧)
上述3种情形还有三种对称的情形。
删除的情形以及其应对的策略如下:
图3 删除的情形(一侧)
代码:
测试结果:
1,算法导论 红黑树章节
2,http://chiyx.iteye.com/blog/1663013
红黑树的左旋和右旋
图1 左旋和右旋示意图
左旋的伪代码:
LEFT-ROTATE(T,x) y = x.right x.right = y.left if y.left != nil(T) y.left.p = x y.p = x.p if x.p == nil(T) T.root = y elseif x == x.p.left x.p.left = y else x.p.right = y y.left = x x.p = y
代码很好理解,不用赘述,右旋可以参照给出,很简单。
红黑树的插入情况可以修改二叉查找树的插入函数完成插入,同理删除情况也是如此。
插入可能导致的情形及应对的策略有下面几种:
图2 插入的情形(一侧)
上述3种情形还有三种对称的情形。
删除的情形以及其应对的策略如下:
图3 删除的情形(一侧)
代码:
#include <iostream> #include <assert.h> #include <stack> #include <queue> #include <iomanip> using namespace std; #define BLACK 0 #define RED 1 typedef struct RBTreeNode* RBTree; typedef struct RBTreeNode{ int data; int color; RBTree lchild,rchild,parent; } RBTreeNode ; RBTree createNode(int key) { RBTree ptr = new RBTreeNode; ptr->data = key; ptr->parent = NULL; ptr->color = RED; ptr->lchild = NULL; ptr->rchild = NULL; return ptr; } RBTree& grandparent(RBTree ptr) { /* parameter n is short for node */ return ptr->parent->parent; } RBTree uncle(RBTree n) { /* parameter n is short for node */ if ( n->parent == grandparent(n)->lchild) return grandparent(n)->rchild; else return grandparent(n)->lchild; } RBTree minimum(RBTree ptr) { while (ptr->lchild != NULL) { ptr = ptr->lchild; } return ptr; } RBTree succ(RBTree ptr) { if (ptr->rchild != NULL) return minimum(ptr->rchild); /*RBTree y = n->parent; while (y != NULL && n == y->rchild){ n = y; y = y->parent; } return y;*/ } RBTree leftRotate(RBTree *T,RBTree x) { /* | x / \ # y / \ # # */ RBTree y = NULL; RBTree root =NULL; y = x->rchild; x->rchild = y->lchild; if (y->lchild != NULL) { y->lchild->parent = x; } y->parent = x->parent; if (x->parent == NULL) { root = y;// x = y? } else if (x->parent->lchild == x) x->parent->lchild = y; else x->parent->rchild = y; y->lchild = x; x->parent = y; if (root) *T = root; return y; } RBTree rightRotate(RBTree *T,RBTree y) { /* | y / \ x # / \ # # */ RBTree x =NULL; x = y->lchild; RBTree root = NULL; y->lchild = x->rchild; if (NULL != x->rchild) { x->rchild->parent = y; cout<<"Runned?"<<endl; } if (y->parent != NULL) x->parent = y->parent; else x->parent = NULL; if ((y)->parent == NULL) root = x; else { if (y->parent->rchild = y) y->parent->rchild = x; else y->parent->lchild = x; } x->rchild = y; y->parent = x; if (root) *T = root; return x; } void RBInsertFixup(RBTree *T,RBTree z) { RBTree y; RBTree p; while ((p = z->parent) != NULL && p->color == RED) { if (p == grandparent(z)->lchild){ /* parent of z is the lef child of grand parent of z */ y = uncle(z); if (y != NULL && y->color == RED){ /* case 1 : color flip*/ z->parent->color = BLACK; grandparent(z)->color = RED; y->color = BLACK; z = grandparent(z); } else { if (z == z->parent->rchild) { /* case 2 */ z = z->parent; leftRotate(T,z); } //* case 3*/ / z->parent->color = BLACK; grandparent(z)->color = RED; rightRotate(T,z->parent->parent); } } else { /* z->p = z->p->p->rchild */ y = uncle(z); if (y != NULL && y->color == RED){ /*case 4 */ z->parent->color = BLACK; grandparent(z)->color = RED; y->color = BLACK; z = grandparent(z); } else { if (z == z->parent->lchild) { /*case 5*/ z = z->parent; rightRotate(T,z); } /*case 6*/ z->parent->color = BLACK; grandparent(z)->color = RED; leftRotate(T,z->parent->parent); } } } (*T)->color = BLACK; } void RBDeleteFixup(RBTree *T,RBTree xp,RBTree x) { /* xp is parent of x */ RBTree w; while( x != *T && (x == NULL || x->color == BLACK)) { if (x == xp->lchild){ /* w is sibling of x */ w = xp->rchild; if (w->color == RED){ //case 1 w->color = BLACK; x->parent->color = RED; leftRotate(T,x->parent); w = xp->rchild; } if ((w->lchild == NULL || w->lchild->color == BLACK) && (w->rchild == NULL || w->rchild->color == BLACK)){ //case 2 w->color = RED; x = xp; xp = xp->parent; } else { if (w->rchild == NULL || w->rchild->color == BLACK){ // case 3 w->lchild->color = BLACK; w->color = RED; rightRotate(T,w); w = xp->rchild; } // case 4 w->color = xp->color; xp->color = BLACK; w->rchild->color = BLACK; leftRotate(T,xp); x = *T; } } else { /* x == xp->rchild and w is sibling of x*/ w = xp->lchild; if (w->color == RED){ //case 1 w->color = BLACK; xp->color = RED; rightRotate(T,xp); w = xp->lchild; } if ((w->lchild == NULL || w->lchild->color == BLACK) && (w->rchild == NULL || w->rchild->color == BLACK)){ //case 2 w->color = RED; x = xp; xp = xp->parent; } else { if (w->lchild == NULL || w->lchild->color == BLACK){ // case 3 w->rchild->color = BLACK; w->color = RED; leftRotate(T,w); w = xp->lchild; } // case 4 w->color = xp->color; xp->color = BLACK; w->lchild->color = BLACK; rightRotate(T,xp); x = *T; } } } if (x != NULL) x->color = BLACK; } void RBInsert(RBTree *T,int key) { RBTree z = createNode(key); assert(z != NULL); RBTree y = NULL; RBTree x = *T; while (x != NULL) { y = x; if ( z->data < x->data) x = x->lchild; else if (z->data == x->data) { cout<<"Key = "<<z->data<<" is already in the RB-Tree."<<endl; delete z; return; } else { x = x->rchild; } } z->parent = y; if (y == NULL) { *T = z; } else if (z->data < y->data) { y->lchild = z; } else { y->rchild = z; } z->lchild = NULL; z->rchild = NULL; z->color = RED; RBInsertFixup(T,z); } void RBDelete(RBTree *T,int key) { RBTree z = *T; RBTree x,y; x = y = NULL; bool found = false; while ( z != NULL) { if (key < z->data) z = z->lchild; else if (key > z->data) z = z->rchild; else { found = true; break; } } if (!found) { cout<<"Key = "<<key<<" is not in the tree."<<endl; return; } /* copy data of y into z and delete y*/ if (z->lchild == NULL || z->rchild == NULL) y = z; else y = succ(z); /* x will be subtree of y */ if (y->lchild != NULL) { x = y->lchild; } else /* is it ok? */ x = y->rchild; /* x link to parent of y */ if (x != NULL) x->parent = y->parent; if(y->parent == NULL) { /* if y is the root of Tree */ *T = x; } else if (y == y->parent->lchild) y->parent->lchild = x; else y->parent->rchild = x; if (y != z) { /* copy data of y into z */ z->data = y->data; } if (y->color == BLACK) RBDeleteFixup(T,y->parent,x); delete y; } inline int max(int a,int b) { return a>b?a:b; } int Height(RBTree T) { if (T == NULL) return 0; else return 1 + max(Height(T->lchild), Height(T->rchild)); } void MakeMat(RBTree T,int root_x,int root_y,int step,int **m) { int lChildPos,rChildPos; lChildPos = root_x - step; rChildPos = root_x + step; if (T == NULL) return; else { m[root_y][root_x] = 1; MakeMat(T->lchild,lChildPos,root_y+1,step>>1,m); MakeMat(T->rchild,rChildPos,root_y+1,step>>1,m); } } void RBTreeDisplay(RBTree T) { if(T == NULL) return; /* init placehold flags m[h][len] */ int h = Height(T); int len = (1<<h) - 1; int row = h; int **m = new int*[row]; for(int i= 0;i<row;i++){ m[i] = new int[len]; memset(m[i],0,len*sizeof(int)); } /* get level order traversal sequence */ vector<RBTree> v; queue<RBTree> q; queue<RBTree> qt; q.push(T); RBTree pt; while(!q.empty()) { pt = q.front(); if (pt->lchild != NULL) q.push(pt->lchild); if(pt->rchild != NULL) q.push(pt->rchild); v.push_back(pt); q.pop(); } /* generate output matrix plus '/' and '\\' m[2*h-1][len] */ MakeMat(T,len>>1,0,len+1>>2,m); /* generate output */ int cnt = 0; int width = 2; for(int i = 0; i < row; i++) { for(int j = 0; j < len; j++) { if(m[i][j]) { cout<<((v[cnt])->color?'R':'B')<<":"<<(v[cnt])->data; cnt++; } else cout<<setw(width)<<' '; } cout<<endl; } } int main() { RBTree T = NULL; int i; int a[] = {12,1,9,0,2,11,7}; for (i = 0; i < 7; i++) { cout<<"Inserting key = "<<a[i]<<endl; RBInsert(&T,a[i]); RBTreeDisplay(T); cout<<endl; cout<<"----------------------------------------------------------"<<endl;; } cout<<"Inserting key = "<<2<<endl; RBInsert(&T,2); RBTreeDisplay(T); cout<<endl; cout<<"----------------------------------------------------------"<<endl; cout<<"Deleting key = "<<2<<endl; RBDelete(&T,2); RBTreeDisplay(T); cout<<endl; cout<<"----------------------------------------------------------"<<endl; cout<<"Deleting key = "<<7<<endl; RBDelete(&T,7); RBTreeDisplay(T); cout<<endl; cout<<"----------------------------------------------------------"<<endl; for (i = 0;i < 7;i++) { cout<<"Deleting key = "<<a[i]<<endl; RBDelete(&T,a[i]); RBTreeDisplay(T); cout<<endl; cout<<"----------------------------------------------------------"<<endl; } }
测试结果:
Inserting key = 12 B:12 ---------------------------------------------------------- Inserting key = 1 B:12 R:1 ---------------------------------------------------------- Inserting key = 9 B:9 R:1 R:12 ---------------------------------------------------------- Inserting key = 0 B:9 B:1 B:12 R:0 ---------------------------------------------------------- Inserting key = 2 B:9 B:1 B:12 R:0 R:2 ---------------------------------------------------------- Inserting key = 11 B:9 B:1 B:12 R:0 R:2 R:11 ---------------------------------------------------------- Inserting key = 7 B:9 R:1 B:12 B:0 B:2 R:11 R:7 ---------------------------------------------------------- Inserting key = 2 Key = 2 is already in the RB-Tree. B:9 R:1 B:12 B:0 B:2 R:11 R:7 ---------------------------------------------------------- Deleting key = 2 B:9 R:1 B:12 B:0 B:7 R:11 ---------------------------------------------------------- Deleting key = 7 B:9 B:1 B:12 R:0 R:11 ---------------------------------------------------------- Deleting key = 12 B:9 B:1 B:11 R:0 ---------------------------------------------------------- Deleting key = 1 B:9 B:0 B:11 ---------------------------------------------------------- Deleting key = 9 B:11 R:0 ---------------------------------------------------------- Deleting key = 0 B:11 ---------------------------------------------------------- Deleting key = 2 Key = 2 is not in the tree. B:11 ---------------------------------------------------------- Deleting key = 11 ---------------------------------------------------------- Deleting key = 7 Key = 7 is not in the tree. ----------------------------------------------------------REF:
1,算法导论 红黑树章节
2,http://chiyx.iteye.com/blog/1663013
相关文章推荐
- 红黑树(Red-Black tree)(插入与删除操作)
- Red-Black Tree红黑树(插入操作)
- 红黑树插入删除节点过程分析 && C代码实现
- RB_TREE 红黑树插入及删除
- 解析《算法导论》中红黑树的插入和删除算法
- 红黑树(red-black tree)
- [Data Structure] 红黑树( Red-Black Tree ) - 笔记
- 数据结构:红黑树插入与删除
- 红黑树 自底向上和自顶向下插入, 自顶向下删除
- 1135. Is It A Red-Black Tree (30)(判断红黑树)
- 红黑树插入操作和删除的代码
- 红黑树插入与删除
- 红黑树插入删除操作
- 红黑树插入与删除 算法实现+代码(二)
- 1135. Is It A Red-Black Tree (30)/红黑树 搜索建树
- 红黑树插入和删除结点的全程演示
- 红黑树的基本插入和删除操作
- 红黑树-JAVA实现(红黑树插入和删除)
- 1135. Is It A Red-Black Tree (30) 红黑树
- 红黑树从头至尾插入和删除结点的全程演示图