#include <stdio.h>
  #include <stdlib.h>
  //////////////////////////////////////////////////////////////////////
  
  #define RED        0    // 红色节点
  #define BLACK    1    // 黑色节点
  
  typedef int Type;
  
  // 红黑树的节点
  typedef struct RBTreeNode{
     unsigned char color;        // 颜色(RED 或 BLACK)
     Type   key;                    // 关键字(键值)
     struct RBTreeNode *left;    // 左孩子
     struct RBTreeNode *right;    // 右孩子
     struct RBTreeNode *parent;    // 父结点
  }Node, *RBTree;
 // 红黑树的根
  typedef struct rb_root{
     Node *node;
  }RBRoot;
 
 RBRoot* create_rbtree();
 Node* rb_parent(Node* n);
 Node* create_node(Type key, Node *parent, Node *left, Node* right);
 void left_rotate(RBRoot *root, Node *x);
 void right_rotate(RBRoot *root, Node *y);
 static void insert_fixup(RBRoot *root, Node *node);
 int  insert(RBRoot *root, Node *node);
  static void inorder(Node *root);
  static Node* rbtree_search(RBRoot* root, Type key);
  void rb_delete_fixup(RBRoot *root, Node *parent,Node *node);
  void rb_delete(RBRoot *root, Node *del);
    
  //#define rb_is_black(r)  ((r)->color==BLACK)
  //#define rb_set_black(r)  do { (r)->color = BLACK; } while (0)
  //#define rb_set_red(r)  do { (r)->color = RED; } while (0)
  #define rb_set_parent(r,p)  do { (r)->parent = (p); } while (0)
  #define rb_set_color(r,c)  do { (r)->color = (c); } while (0)
  inline  bool rb_is_red(Node *n) { if(n)  return n->color==RED ; else return  false; }
  inline  bool rb_is_black(Node*n) {  return n->color==BLACK; }
  inline  void rb_set_black(Node*n) {   n->color=BLACK; }
  inline  void rb_set_red(Node*n) {   n->color=RED; } 
  bool rb_is_red(Node *node);
// #endif
//=========================================================================================================================
int main()
{
    RBRoot* root =create_rbtree();
    Node* n= create_node(3, NULL, NULL, NULL);
    
    int  a[100]={13,45,23,7,8,9,11,14,16,18, 29, 33, 31, 6, 3, 2, 42};
    for( int i=0;i<10;i++)
    {
        n= create_node(a[i], NULL, NULL, NULL);
        insert(root,n);
    }
    inorder(root->node);
    printf("\n");
    Node* del=rbtree_search(root,23);
    if(del)
        rb_delete(root,del);
    inorder(root->node);
    
    return 0;
}

static void inorder(Node *root)
  {
      if(root != NULL)
      {
          inorder(root->left);
          printf("%d ", root->key);
          inorder(root->right);
      }
  }
/*
  * 创建红黑树,返回"红黑树的根"!
    */
  RBRoot* create_rbtree()
  {
      RBRoot *root = (RBRoot *)malloc(sizeof(RBRoot));
      root->node = NULL;
      return root;
  }
  
  Node* create_node(Type key, Node *parent, Node *left, Node* right)
 {
     Node* p;
 
    if ((p = (Node *)malloc(sizeof(Node))) == NULL)
         return NULL;
     p->key = key;
     p->left = left;
     p->right = right;
     p->parent = parent;
     p->color = BLACK; // 默认为黑色
 
     return p;
 }
 /* 
227  * 对红黑树的节点(x)进行左旋转
228  *
229  * 左旋示意图(对节点x进行左旋): 右子变父,父变左子 
230  *      px                              px
231  *     /                               /
232  *    x                               y                
233  *   /  \      --(左旋)-->           / \                #
234  *  lx   y                          x  ry     
235  *     /   \                       /  \
236  *    ly   ry                     lx  ly  
237  *
238  *
239  */
 void left_rotate(RBRoot *root, Node *x)
 {
     // 设置x的右孩子为y
     Node *y = x->right;
 
     // 将 “y的左孩子” 设为 “x的右孩子”;
     // 如果y的左孩子非空,将 “x” 设为 “y的左孩子的父亲”
     x->right = y->left;
     if (y->left != NULL)
         y->left->parent = x;
 
     // 将 “x的父亲” 设为 “y的父亲”
     y->parent = x->parent;
 
     if (x->parent == NULL)
     {
         root->node = y;            // 如果 “x的父亲” 是空节点,则将y设为根节点
     }
     else
     {
         if (x->parent->left == x)
             x->parent->left = y;    // 如果 x是它父节点的左孩子,则将y设为“x的父节点的左孩子”
         else
             x->parent->right = y;    // 如果 x是它父节点的右孩子,则将y设为“x的父节点的右孩子”
     }
     
     // 将 “x” 设为 “y的左孩子”
     y->left = x;
     // 将 “x的父节点” 设为 “y”
     x->parent = y;
 }
 
/* 
274  * 对红黑树的节点(y)进行右旋转
275  *
276  * 右旋示意图(对节点y进行左旋):
277  *            py                               py
278  *           /                                /
279  *          y                                x                  
280  *         /  \      --(右旋)-->            /  \                     #
281  *        x   ry                           lx   y  
282  *       / \                                   / \                   #
283  *      lx  rx                                rx  ry
284  * 
285  */
  void right_rotate(RBRoot *root, Node *y)
 {
     // 设置x是当前节点的左孩子。
     Node *x = y->left;
 
     // 将 “x的右孩子” 设为 “y的左孩子”;
     // 如果"x的右孩子"不为空的话,将 “y” 设为 “x的右孩子的父亲”
     y->left = x->right;
     if (x->right != NULL)
         x->right->parent = y;
     // 将 “y的父亲” 设为 “x的父亲”
     x->parent = y->parent;
     if (y->parent == NULL) 
     {
         root->node = x;            // 如果 “y的父亲” 是空节点,则将x设为根节点
     }
     else
     {
         if (y == y->parent->right)
             y->parent->right = x;    // 如果 y是它父节点的右孩子,则将x设为“y的父节点的右孩子”
         else
             y->parent->left = x;    // (y是它父节点的左孩子) 将x设为“x的父节点的左孩子”
     }
 
     // 将 “y” 设为 “x的右孩子”
     x->right = y;
       // 将 “y的父节点” 设为 “x”
     y->parent = x;
 }
 
 /*
321  * 红黑树插入修正函数
322  *
326  * 参数说明:
327  *     root 红黑树的根
328  *     node 插入的结点        
329  */
 static void insert_fixup(RBRoot *root, Node *node)
 {
    Node *parent, *gparent;
    //由于插入结点都是红色  如果插入结点的父结点是黑色,不影响红黑树平衡,无需调整 ,
    //因此只需考虑父结点为红色的情况 
    // 若“父节点存在,并且父节点的颜色是红色”
    while ((parent = node->parent) && rb_is_red(parent))
    {
             gparent = parent->parent;   //因为父结点是红色,祖父必然是黑色 
             
             //情况1:叔叔结点存在且是红色  
             Node *uncle = gparent->left==parent? gparent->right:gparent->left;//父是左子,则叔是右子,反之 
             if (uncle && rb_is_red(uncle))
             {
                        rb_set_black(uncle);   //父辈都翻黑 
                        rb_set_black(parent);  //父辈都翻黑 
                        rb_set_red(gparent);   //祖辈翻红 
                        node = gparent;        //由于祖辈翻红, 会与祖辈的上辈违反红黑树的要求,因此 把祖辈设为当前结点,继续调整 
                        continue;
             }
             //情况2: 以下是叔叔不存在或者为黑色的情况 其实 叔叔只能不存在,不可能为黑色 
             
             //情况2.1  若“父节点”是“祖父节点的左孩子”
             if (parent == gparent->left)
             {
                    
                    //情况2.1.1  插入结点是父节点的右孩子
                    if (parent->right == node)
                     {
                         left_rotate(root,parent);   //先把父左旋  变成 左-左使之与2.1.2称为一样的形态  调整还没有完成, 到2.1.2进一步调整 
                        Node *tmp= parent;         //左旋后,父子地位互换, 要把父设为当前结点node,而node变为父,才能在2.1.2中得到进一步处理 
                        parent = node; 
                        node = tmp;
                        
                     }
                     //情况2.1.2  插入结点是父节点的左孩子   左-左 
                     {
                         rb_set_black(parent);  //父亲变黑 
                         rb_set_red(gparent);   //祖父变红 
                         right_rotate(root, gparent); //把祖父右旋转  
                    }
              }
             //情况2.2 若“父节点”是“祖父节点的右孩子”
             else 
             {
                     //情况2.2.1  插入结点是父节点的左孩子
                    if (parent->left == node)
                     {
                         right_rotate(root,parent);   //先把父右旋  变 右-左    为右-右 使之与2.2.2一样的形态,到2.2.2中进一步调整 
                        Node *tmp= parent;         //右旋后,父子地位互换, 要把父设为当前结点node,而node变为父
                        parent = node; 
                        node = tmp;  
                     }
                     //情况2.2.2  插入结点是父节点的右孩子
                     {
                         
                        rb_set_black(parent);  //父亲变黑 
                         rb_set_red(gparent);   //祖父变红 
                         left_rotate(root, gparent); //把祖父左旋转 
                   }
             }
             
    }
             
    // 将根节点设为黑色
    rb_set_black(root->node);
 }

 /*
407  * 添加节点:将节点(node)插入到红黑树中
408  *
409  * 参数说明:
410  *     root 红黑树的根
411  *     node 插入的结点        
412  */
 int  insert(RBRoot *root, Node *node)
 {
     Node *y = NULL;
     Node *x = root->node;  
 
     // 1. 将红黑树当作一颗二叉查找树,将节点添加到二叉查找树中。
     while (x != NULL)         //y迭代当前结点,x迭代当前结点的左右子结点 
     {
         y = x;
         if (node->key < x->key)
             x = x->left;
         else if (node->key > x->key) 
             x = x->right;
         else                        //找到相等的key了 
             return -1;    //key值已经存在 插入失败  
     }
     node->parent = y;
     if (y != NULL)
     {
         if (node->key < y->key)
             y->left = node;                // 情况2:若“node所包含的值” < “y所包含的值”,则将node设为“y的左孩子”
         else 
             y->right = node;            // 情况3:(“node所包含的值” >= “y所包含的值”)将node设为“y的右孩子”
         
     }
     else
     {
         root->node = node;                // 情况1:若y是空节点,则将node设为根
     }
     // 2. 设置插入节点的颜色为红色
     node->color = RED;
     // 3. 将它重新修正为一颗红黑树
     insert_fixup(root, node);
     return  1;
 }
 
 void rb_delete(RBRoot *root, Node *del)
 {
     Node *child=NULL, *parent;
     int color;
     
     // 先处理被删除节点的"左右孩子都不为空"的情况,找到它的替代点, 再把替代点变为真正要删除的结点 
     if ( (del->left!=NULL) && (del->right!=NULL) ) 
     {
             //搜寻替代结点 
            Node *replace = del;    
            replace = replace->right;   
            while (replace->left != NULL)
                    replace = replace->left;
            
            // (1)用替代结点替换删除结点   
            if(del->parent)
            {
                if(del->parent->left==del) del->parent->left=replace;  
                else                       del->parent->right=replace;
            }
            else  root->node = replace;
            //记录替代节点的父亲和孩子  
            parent =replace->parent;
            child = replace->right;   //替代结点只有右子 
            color = replace->color;
                            
            //替代结点脱离原来的关系     
            if(parent==del)      // 如果替代结点的父亲恰好就是删除结点
            {
                parent= replace;   // 此时关系是    del->右-> replace->右->child  所以 child无需和替代结点R脱离 ,替代点就是child的父亲
            }
            else{
                 if(child ) child->parent = parent;
                 parent->left  =child;
                 // (2)用替换结点变为删除结点//    // 放到这里是因为避免出现删除结点是替代结点的父亲的情况,从而导致替代结点的右子结点指向自己
                 replace->right = del->right;     
                 del->right->parent    = replace; 
            }
            // 经过(1)(2)(3)三步才完成替换了删除结点 
            //替代删除结点为替代结点一共有6个操作,分别是设置左子结点(2个),右子结点(2个),父亲结点(2个)
            // (3) 用替换结点变为删除结点     
            replace->parent = del->parent;
            replace->color = del->color;
            replace->left = del->left;
            del->left->parent = replace;
            
            if(color==BLACK)
                rb_delete_fixup(root, parent,child) ;   
        
     }
     //剩下都是被删点为单子树的情况
     //情况 A)  被删除结点是红色  则被删除结点的左或着右孩子必为空  直接删除,不需调整 
     //情况 B) 被删除结点为黑  被删除的黑结点如有孩子, 则孩子必是红色  删除后  孩子变黑既可,后续无需调整 
     //情况 C) 被删除的黑结点无孩子 ,要修正 
     else    
     {
              if(del->right)
                    child =del->right ;
             else child = del->left;
              
             parent=del->parent;
              color = del->color;
              
              //删除点从树中脱离 
             if(child)  {
                 child->parent =parent;
                 child->color  =BLACK;   //被删除的黑结点如有孩子, 则孩子必是红色, 删去黑结点, 让孩子变黑达到平衡 
             }   
             
             if(parent)  {
                  if(parent->left==del)  parent->left = child;
                  else  parent->right = child;
             }  
             else  root->node =child;
             
             if(color==BLACK && child==NULL)  //黑结点且无孩子,则需要修正 
                 rb_delete_fixup(root, parent,child) ;     
     }
     
     free(del);
     rb_set_black(root->node);
 }
 
 
 /*
501  * 红黑树删除修正函数
502  *
503  * 在从红黑树中删除插入节点之后(红黑树失去平衡),再调用该函数;
504  * 目的是将它重新塑造成一颗红黑树。
505  *
506  * 参数说明:
507  *     root 红黑树的根
508  *     node 待修正的节点
509  */
 inline void rb_delete_fixup(RBRoot *root, Node *parent,Node *node) 
 {
     Node* brother;  //被删除黑结点必有兄弟,否则以parent为根的子树不能平衡 
     while(  ( !node || rb_is_black(node) ) && node!=root->node )
     {
          /**
             * 分为四种情况,分别是
             * 1.兄弟结点是红色
             * 2.兄弟结点是黑色,其子结点也是黑色
             * 3.兄弟结点是黑色,其左子结点为红色,右子结点任意颜色 
             * 4.兄弟结点是黑色,其左子结点任意颜色,右子结点为红色
             */

          
          //分两大情况, 1 删除结点是父亲左孩子, 2 删除结点是父亲右孩子 
        if (parent->left == node)
        {
            brother= parent->right;  //兄弟是右 
            if (rb_is_red(brother) )  //1 若兄弟是红色, 为保证平衡,则兄弟必有两个黑子树 
            {
                brother->color=BLACK;  
                parent->color =RED;
                left_rotate(root, parent);    //旋转后,仍不平衡,此时,删除结点的兄弟变了,是原兄弟的左黑子树 ,因此兄弟要重设 
                brother = parent->right;    //重设兄弟, 现在的兄弟是黑色,转到下面黑兄弟的情况执行 
            }
            //以下都是黑兄弟的情况  根据平衡条件 黑兄弟只能有红孩子.  分有左红孩子, 有右红孩子,没孩子三种情况 
            if( brother->left && rb_is_red(brother->left) )  //3 兄弟有左红孩子 
            {
                         brother->left->color = parent->color; // brother的左红孩子变为父亲的颜色 
                         rb_set_black(parent);   //父亲变黑 
                         right_rotate(root, brother);  //兄弟右旋转, 左红孩子上位 
                         left_rotate(root,parent); //父亲左旋,补充左边的黑子数目 
                         break;
                         
            }
            else if(brother->right && rb_is_red(brother->right) ) //4 兄弟有右红孩子 
            {
                         brother->color = parent->color; // brother变为父亲的颜色 
                         rb_set_black(brother->right);    //兄弟右红孩子变黑 
                         rb_set_black(parent);   //父亲变黑
                         left_rotate(root,parent); //父亲左旋,补充左边的黑子数目
                         break;
            }
            else  // 2  黑兄弟只有黑孩子,或者没孩子 
            {
                        //又分两种情况  父为红, 父为黑 
                if( rb_is_red(parent) ) // 父为红
                {
                            rb_set_black(parent);   //父亲变黑  补充删去的黑结点 
                            rb_set_red(brother);    //为保证平衡, 兄弟变为红
                            break;
                }
                else // 父为黑 
                {
                            rb_set_red(brother);    //为保证平衡, 兄弟只能变为红
                            node =parent;          //父亲作为子树比其他树要少一个黑点了,因此要把 父亲当作新的待平衡点, 继续循环 上溯继续平衡 
                }
            } 
        }
        //2大情况 删除结点是父亲右孩子 
        else
        {
             brother= parent->left;   //兄弟是左 
            if (rb_is_red(brother) )  //1 若兄弟是红色, 为保证平衡,则兄弟必有两个黑孩子 
            {
                rb_set_black(brother);
                rb_set_red(parent);
                right_rotate(root, parent);    //旋转后,仍不平衡,此时,删除结点的兄弟变了,是黑兄弟 ,因此兄弟要重设 
                brother = parent->left;    //重设兄弟, 转到下面兄弟为黑兄弟的情况执行 
            }
            //以下都是黑兄弟的情况  根据平衡条件 黑兄弟只能有红孩子.  分有左红孩子, 有右红孩子,没孩子三种情况 
                
            if( brother->left && rb_is_red(brother->left) )  //兄弟有左红孩子 
            {
                         brother->color = parent->color; // brother变为父亲的颜色 
                         rb_set_black(brother->left);    //兄弟左红孩子变黑 
                         rb_set_black(parent);   //父亲变黑
                         right_rotate(root,parent); //父亲右旋,补充右边的黑子数目
                         break;
                         
                         
            }
            else if( brother->right && rb_is_red(brother->right)) //兄弟有右红孩子 
            {
                        brother->right->color = parent->color; // brother的右红孩子变为父亲的颜色 
                        rb_set_black(parent);   //父亲变黑 
                        left_rotate(root, brother);  //兄弟左旋转, 右红孩子上位 
                        right_rotate(root,parent); //父亲右旋,补充右边的黑子数目 
                        break;      
            }
            else  //黑兄弟没孩子的情况
            {
                //又分两种情况  父为红, 父为黑 
                if( rb_is_red(parent) ) // 父为红
                {
                            rb_set_black(parent);   //父亲变黑  补充删去的黑结点 
                            rb_set_red(brother);    //为保证平衡, 兄弟变为红
                            break;
                }
                else // 父为黑 
                {
                            rb_set_red(brother);    //为保证平衡, 兄弟只能变为红
                            node =parent;          //父亲作为子树比其他树要少一个黑点了,因此要把 父亲当作新的待平衡点,上溯继续平衡
                }
            } 
        }
        
         
     }  //循环结束 
     
          
     //if (node)
        // rb_set_black(node);
 }
 Node* rbtree_search(RBRoot* root, Type key)
{
    Node* x=root->node;
     while ((x!=NULL) && (x->key!=key))
     {
         if (key < x->key)
             x = x->left;
         else
             x = x->right;
     }
 
     return x;
 }    

07-27 18:10