数据结构_红黑树

  

// 数据结构_红黑树.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>

/*红黑树
我们知道一颗高度为h的二叉查找树,可以实现任何一种基本的动态集合操作
其时间都是 O(h),当树的高度很低时,这些操作会很快,但当树的高度很高时,这些操作可能可能不比链表好
红黑树是许多平衡的查找树的一种,它能保证在最坏的情况下,基本的动态集合的操作时间为O(lgn)

树中每个结点都包含五个域:color,key,left,right,p.我们把指向NIL的指针视为指向外结点的指针,而把关键字的结点视为内结点
一颗二叉查找树如果满足下面的红黑性质,则为一颗红黑树
1) 每个结点或是红的,或是黑的
2)根结点是黑的
3) 每个叶结点(NIL)都是黑的
4)如果一个结点是红的,则它的两个儿子都是黑的
5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点

从某个结点x出发(不包含该结点)到达一个叶结点的任意的一条路径上,黑色结点的个数称为该结点x的黑高度
红黑树的黑高度,定义为其根结点的黑高度*/

enum COLOR{

 RED,
 BLACK
};

typedef struct RBTREE{

 RBTREE *left;
 RBTREE *right;
 RBTREE *p;
 int key;
    COLOR color;
}RBTREE,*PRBTREE;

PRBTREE nil,root;

RBTREE *tree_minimum(RBTREE *x){

 while(nil != x->left){

  x = x->left;
 }
 
 return x;
}

 

RBTREE *tree_successor(RBTREE *x){

 PRBTREE y = NULL;

 if(x->right != nil){

  return tree_minimum(x->right);// x 的右子树的最左孩子就是x的后继
 }

 y = x->p;// x结点没有右子树,如果x是其父结点的左孩子,直接返回x的父结点

 while((y != nil) &&(x == y->right)){//如果x结点,是其父结点的右孩子,一直要找一个,其父结点是要找结点的左孩子。返回这个结点

  x = y;

  y = y->p;
 }

 return y;
}


/*旋转
当在含有n个关键字的红黑树上运行时,查找和删除,可能违反红黑树的性质,为保持这些性质
就要改变树中某些结点的颜色以及指针结构

指针结构的修改是通过旋转来完成的,这是一种能保持二叉查找树性质的查找树局部操作,有两种旋转,左旋和右旋
当在某个结点x上做左旋转时,我们假设它的右孩子y不是nil[T],x可以为树内任意右孩子不是nil[T]的结点,左旋以
x到y之间的链为支轴进行,它使y成为该子树新的根,x成为y的左孩子,y的左孩子成为x的右孩子
*/
/*
LEFT-ROTATE(T,x)
1 y <- left[x]
2 right[x] = left[y]
3 if left[y] != nil[T]
4 then p[left[y]] <- x
5 p[y] <- p[x]
6 if p[x] = nil[T]
7    then root[T] <- y
8  else if x = left[p[x]]
9        then left[p[x]] <- y
10       else right[p[x]] <- y
11 left[y] <- x
12 p[x] <- y
*/
int left_rotate(RBTREE *x){
 
 PRBTREE y;

 y = x->right;

 x->right = y->left;

 if (nil != y->left){

  y->left->p = x;
 }

 y->p = x->p;

 if(nil == x->p){
 
  root = y;
 
 }else if(x == x->p->left){
 
  x->p->left = y;
 }
 else{

  x->p->right = y;
 }
 y->left = x;

 x->p = y;

 return 0;
}

/*
RIGHT-ROTATE(T,x)
1 y <- right[x]
2 left[x] = right[y]
3 if right[y] != nil[T]
4 then p[right[y]] <- x
5 p[y] <- p[x]
6 if p[x] = nil[T]
7    then root[T] <- y
8  else if x = right[p[x]]
9        then right[p[x]] <- y
10       else left[p[x]] <- y
11 right[y] <- x
12 p[x] <- y
*/
int right_rotate(RBTREE *x){
 
 PRBTREE y;
 
 y = x->left;
 
 x->left = y->right;
 
 if (nil != y->right){
 
  y->right->p = x;
 }
 
 y->p = x->p;
 
 if(nil == x->p){
 
  root = y;
 
 }else if(x == x->p->right){
 
  x->p->right = y;
 }
 else{
 
  x->p->left = y;
 }
 y->right = x;
 
 x->p = y;
 
 return 0;
}
/*
RB-INSERT-FIXUP(T,z)
1 while color[p[z]] = RED
2   do if p[z] = left[p[p[z]]]
3  then y <- right[p[p[z]]]
4   if color[y] = RED
5              then color[p[z]] <- BLACK    Case 1
6        color[y] <- BLACK       Case 1
7     color[p[p[y]]] <- RED   Case 1
8        z <- p[p[z]]            Case 1
9      else if z = right[p[z]]
10     then z <- p[z]   Case 2
11     LEFT_ROTATE(T,z)     Case 2
12        color[p[z]] <- BLACK Case 3
13     color[p[p[z]]] <- RED Case 3
14     RIGHT-ROTATE(T,p[p[z]]) Case 3
15     else (same as the clause with "right" and "left" exchanged)
16 color[root[T]] <- BLACK
*/
int rb_insert_fixup(RBTREE *z){

 PRBTREE y = NULL;
    
 while(RED == z->p->color){

      if(z->p == z->p->p->left){

       y = z->p->p->right;
  
   if(RED == y->color){

    z->p->color = BLACK;
    y->color = BLACK;
    z->p->p->color = RED;
    z = z->p->p;
   }
   else if(z == z->p->right){

    z = z->p;

    left_rotate(z);
   }
   else{
    z->p->color = BLACK;
    z->p->p->color = RED;
    right_rotate(z->p->p);
   }
   }
  
  
   else{
   
       y = z->p->p->left;
  
   if(RED == y->color){

    z->p->color = BLACK;
    y->color = BLACK;
    z->p->p->color = RED;
    z = z->p->p;
   }
   else if(z == z->p->left){
   
    z = z->p;
    right_rotate(z);
   }
   else{
  

   
    z->p->color = BLACK;
    z->p->p->color = RED;
    left_rotate(z->p->p);
   }
   
  
   }

 
 }

 root->color = BLACK;

 return 0;
}
/*
插入
RB-INSERT(T,z)
1 y <- nil[T]
2 x <- root[T]
3 while x != nil[T]
4   do y <- x
5      if key[z] < key[x]
6    then x <- left[x]
7    else x <- right[x]
8 p[z] <- y
9 if y = nil[T]
10  then root[T] <- z
11 else if key[z] < key[y]
12          then left[y] <- z
13      else right[y] <- z
14 left[z] <- nil[T]
15 right[z] <- nil[T]
16 color[z] <- RED
17 RB-INSERT-FIXUP(T,z)
*/
int rb_insert(RBTREE *z){

 PRBTREE y = NULL,x = NULL;

 y = nil;

 x = root;

 while(nil != x){

  y = x;
    //根据二叉排序树的性质,左边子树小于根结点,右边子树大于根结点,找到z的父亲
  if(z->key < x->key){

   x = x->left;
  }
  else{

   x = x->right;
  }
 }

 //设置z的父结点
 z->p = y;
   
    //当我们第一次插入根结点时,y等于nil,直接将root设置成z.
 if(nil == y){

  root = z;
 }
 //设置z的父亲的孩子结点
 else if(z->key < y->key){

  y->left = z;
 }
 else{

  y->right = z;
 }
    //设置待插入结点的左右孩子,color域
 z->left = nil;
 
 z->right = nil;

 z->color = RED;

 //结点的插入完毕,进行红黑树性质的保持。

 rb_insert_fixup(z);

 return 0;
}
/*和n个结点的红黑树上的其他操作基本操作一样,对一个结点的删除要花O(lg n)的时间 */
/*
RB-DELETE(T,z)
1 if left[z] = nil[T] or right[z] = nil[T]
2 then y <- z
3 else y <- TREE-SUCCESSOR(z)
4 if left[y] != nil[T]
5 then x <- left[y]
6 else x <- right[y]
7 p[x] <- p[y]
8 if p[y] = nil[T]
9    then root[T] <- x
10   else if y = left[p[y]]
11    then left[p[y]] <- x
12        else right[p[y]] <- x
13 if y != x
14   then key[z] <- key[y]
15      copy y's statlite data into z
16 if color[y] = BLACK
17  then RB-DELETE-FIXUP(T,x)
18 return y
过程TREE-DELETE和RB-DELETE之间有三点不同,首先,TREE-DELETE中所有对NIL的引用在RB-DELETE中都被替换成对哨兵nil[T]的引用
其次,TREE-DELETE的第七行中的判断x是否为NIL的测试被去掉了,取而代之,无条件执行p[x] <- p[y],这样,如果x是哨兵nil[T],其父指针就指向被删除的结点y的父亲。第三
在第16,17行如果y是黑色的,则调用RB-DELETE-FIXUP,如果y是红色的,则当y被删除后,红黑性质得以保持,理由如下:
 树中的各结点的黑高度没有变化
 不存在相邻的红色结点
 如果y是红色的,就不可能是根,所以根仍然是黑色的。
*/

int rb_delete_fixup(RBTREE *x);

RBTREE *rb_delete(RBTREE *z){

 PRBTREE y = NULL,x = NULL;

 //如果待删除的结点是叶子结点,或者只有一个孩子
 if(( z->left == nil)||(z->right == nil)){

  y = z;
 }
 else{
  
  //如果待删除的结点有两个孩子,y此时等于z的后继
  y = tree_successor(z);
 }
 //x等于z的孩子,对于z有两个孩子的情况,x等于nil。
 if(y->left != nil){
 
  x  = y->left;
 }
 else{
 
  x = y->right;
 }
 //因为要删除z所以,将z的孩子的父亲设置为z的父亲。
 x ->p = y->p;
 if(y->p == nil){
 
  root = x;
 }
 //设置待删除的z的父亲的左右孩子指针。如果是两个孩子的情况,将其后继的的父亲的孩子设置为nil.
 else if(y = y ->p->left){
 
  y->p->left = x;
 }
 else{
 
  y->p->right = x;
 }
 if(y != x){
 
  z->key = y->key;  // 拷贝后继的值到z中。
 }
 if(y->color == BLACK){
 
  rb_delete_fixup(x);
 }
 return y;
}
/*

传递给RB-DELETE-FIXUP的结点x是两个结点中的一个,在y被删除之前,如果y有个不是哨兵nil[T]的孩子,则x为y的唯一孩子,如果y没有孩子,则x为哨兵nil[T].第7行中的无条件赋值保证
无论x是有关键字的内结点或哨兵nil[T],x现在的父结点都为先前y的父结点
RB-DELETE-FIXUP(T,x)
1 while x != root[T] and color[x] = BLACK
2     do if x = left[p[x]]
3        then w <- right[p[x]]
4     if  color[w] = RED
5      then color[w] <- BLACK                 Case 1
6                      color[p[x]] <- RED     Case 1
7           LEFT-ROTATE(T,p[x])     Case 1 
8                      w <- right[p[x]]      Case 1
9             if color[left[w]] = BLACK and color[right[w]] = BLACK
10               then color[w] <- RED      Case 2
11       x <- p[x]        Case 2
12     else if color[right[w]] = BLACK
13     then color[left[w]] <- BLACK    Case 3
14       color[w] <- RED      Case 3
15       RIGHT-ROTATE(T,w)      Case 3
16          w <- right[p[x]]      Case 3
17     color[w] <- color[p[x]]      Case 4
18     color[p[x]] <- BLACK       Case 4
19     color[right[w]] <- BLACK      Case 4 
20     LEFT-ROTATE(T,p[x])          Case 4
21     x <- root[T]         Case 4
22  else (same as then clause with "right" and "left" exchanged)
23 color[x] <- BLACK

*/

int rb_delete_fixup(RBTREE *x){
 

 PRBTREE w = NULL;

 while((x != root)&&(x->color == BLACK)){
 
  if(x == x->p->left){ //如果x是其父亲的左孩子
 
   w = x->p->right; //w是x的兄弟。

   if(w->color == RED){ //如果x的兄弟是红色的。
   
    w->color = BLACK;
    x->p->color = RED;
    left_rotate(x->p);
    w = x->p->right;//将情况转换为2,3,4情况
   
    if((w->left->color == BLACK)&&(w->right->color == BLACK)){//如果w的左右孩子都是BLACK的,将w的颜色设置为RED.
  
    w->color = RED;
    x = x->p;
   }
    else if(w->right->color == BLACK){ //如果W的右孩子颜色为BLACK.
  
    w->left->color = BLACK; // 将w的左孩子的颜色设置为BLACK,并把w的颜色设置为RED.
    w->color = RED;
    right_rotate(w);
    w = x->p->right;

   }
   }
   else{
  
    w->color = x->p->color;
    x->p->color = BLACK;
    w->right->color = BLACK;
    left_rotate(x->p);
    x = root;
   }
  
  }
  else{
 
    w = x->p->left;

    if(w->color == RED){
   
     w->color = BLACK;
     x->p->color = RED;
     right_rotate(x->p);
     w = x->p->left;
    
    if((w->right->color == BLACK)&&(w->left->color == BLACK)){
  
     w->color = RED;
     x = x->p;
    }
    else if(w->left->color == BLACK){
  
     w->right->color = BLACK;
     w->color = RED;
     left_rotate(w);
     w = x->p->left;

    }
    }
    else{
  
     w->color = x->p->color;
     x->p->color = BLACK;
     w->left->color = BLACK;
     right_rotate(x->p);
     x = root;
    }
 
 
 
  }
  
  x ->color = BLACK;

}

 return 0;

}


int main(int argc, char* argv[])
{
 
   int a[] = {2,3,7,4,6,14,12,9,11,22,20,17,19,18};

   int i = 0;

   PRBTREE ptemp = NULL;

   nil = (RBTREE *)malloc(sizeof(PRBTREE));

   nil->color = BLACK;

   root = (RBTREE *)malloc(sizeof(PRBTREE));

   root->left = nil;

   root->right = nil;

      root->p = nil;

   root = nil;

   for(i = 0;i < 14;i++){

    ptemp = (RBTREE *)malloc(sizeof(PRBTREE));

    ptemp->key = a[i];

    ptemp->left = nil;

    ptemp->right = nil;

    ptemp->p = nil;

    rb_insert(ptemp);


   }


   rb_delete(root->right->left);

   return 0;
 }

 

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值