范文健康探索娱乐情感热点
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

数据结构

  数据结构 --- 红黑树
  和AVL树一样,红黑树也是自平衡二叉搜索树。红黑树同样解决了在特定情况下二叉搜索树会退化成链表的问题。但是红黑树又不像AVL树那样高度平衡,这就让红黑树在插入删除频繁的场合效率优于AVL树。但是在插入和删除操作较少,而查找频繁的场合AVL树则更胜一筹。实际上linux内核中实现了红黑树(linux/rbtree.h)。linux内核使用红黑树来管理和调度进程。 C++标准库的map也是用红黑树来实现的,而nginx中也使用红黑树来实现了定时器。下面我们就来学习一下这个作为很多牛X软件的底层数据结构红黑树(red-black tree)。红黑树的定义和特性
  首先红黑树是一颗BST(二分查找树),但是红黑树每一个节点包含一个额外的域用来存储颜色属性(每一个节点要么为红色,要么为黑色)。一棵红黑树必须满足下面的性质:每一个节点都有颜色,或者为黑色或者为红色红黑树的根节点必须是黑色的叶子节点(叫做nil或者NULL节点)都是黑色的如果一个红色的节点有子节点,那么子节点必须是黑色的从任意一个节点出发沿着其子节点的所有路径到达叶子节点的黑色深度相同(这里的黑色深度指的是黑色节点的数量)。
  如下图所示的例子就是一颗红黑树:
  对于红黑树的每一个节点都至少包含下面列出的属性:颜色(color)键值(key)左孩子指针(lchild)右孩子指针(rchild)父节点指针(parent,根节点parent为空)
  正是由于红黑树(red-black tree)的五条性质的约束,这使得红黑树从根节点出发到叶子节点的任何一条路径都不可能超过其他从根节点出发到叶子节点路径的两倍,这使得红黑树可以维持平衡。红黑树的基本操作
  和AVL数类似,红黑树在调整平衡时也需要旋转操作。左旋
  左旋操作步骤如下:
  1). 初始状态:
  2). 如果y有左子树,那么将x设为y的左子树β的父节点
  3). 将x的右子树设为β
  4). 如果x的父节点为NULL,那么将y设为根节点
  5). 否则,如果x是其父节点p的左孩子,那么将p的左孩子设为y
  6). 否则,将p的右孩子设为y
  7). 将y的父节点设为p
  7). 将x的父节点设为y
  8). 将y的左子树设为x
  右旋
  右旋的操作步骤如下:
  1). 初始状态
  2). 如果x有右子树,将y设为x右子树β的父节点
  3). 将y的左子树设为β
  4). 如果y的父节点p是NULL,那么将x设为父节点
  5). 否则,如果y是其父节点p的右孩子,那么将x设为p的右孩子
  6). 否则,将x设为p的左孩子
  7). 将x的父节点设为p
  8). 将y的父节点设为x
  9). 将x的右子树设为y
  左右(Left-Right)旋转和右左(Right-Left)旋转
  在左右旋转时,我们先进行左旋,然后再进行右旋,如下步骤:
  1). 先左旋(如下图,对x-y进行左旋)
  2). 再进行右旋(再对y-z进行右旋)
  而我们在进行右左旋转时,是先进行右旋,然后再进行左旋,如下步骤:
  1). 先右旋(如下图,对x-y进行右旋)
  2). 再进行左旋(如下图,对z-y进行左旋)
  红黑树的插入
  对红黑树的插入操作,我们希望插入后对红黑树的5条性质违反越少越好,基于此,我将待插入的节点先标记为红色。然后按照BST的插入方法插入该节点。这里之所以将节点标为红色,是因为这样做可以保证两点,该节点插入后,如果插入位置是根节点,那么违反性质#3,但是这种情况非常容易处理,直接将颜色设为黑色即可。如果插入位置不是根节点,那么它只违反性质#4。只要针对性质#4进行调整即可, 反之标为黑色就会违背#5,对性质#5的调整要比性质#4困难得多。
  插入完成后,我进行调整使其满足红黑树的性质。具体的调整主要是做下面两件事:
  1). 对节点进行颜色调整
  2). 旋转操作
  下面是插入操作的具体步骤:
  1). 将待插入节点标为红色
  2). 首先安装BST插入方法将待插入节点插入, 不清楚BST插入方法的同学可以参考我之前的文章<<数据结构-二叉搜索树>>。
  3). 对插入后的树进行调整(insert fix up)使其仍然保持红黑树的性质。
  我们这里重点来看看insert -fix-up算法:
  我们假设插入的节点为x,p是x的父节点,z是x的祖父节点,那么fix-up的步骤如下:
  1). 如果p的颜色为黑色,那么不需要调整,fix-up结束。
  2). 如果p的颜色为红色,那么违反了#4, 做如下调整:
  3). 如果p是z的左孩子,那么又分为下面三种情况:
  Case 1:如果z的右孩子是红色,那么将z的左孩子和右孩子的节点设为黑色,并将z的颜色设为红色。将x(当前调整的节点)设为z
  Case 2:否则如果当前调整节点x是p的右孩子,那么将x设为p对x进行左右(Left-Right)旋转。
  Case 3:将p的颜色设置为黑色,同时将z的颜色设置为红色对z进行右旋
  4). 否则,做如下调整:如果x的祖父节点z的左孩子是红色的, 那么将z的左孩子和右孩子设为黑色,同时将z设为红色将当前调整节点设为z否则如果当前调整节点x是其父节点p的左孩子,那么将p设为当前调整节点x,并且对x做右旋操作。将x的父节点p设为黑色,祖父节点z设为红色对z进行左旋操作。
  5). 将根节点设为黑色。红黑树的删除
  在红黑树中删除一个节点后,我们依然要保持其红黑树的性质。删除操作要比插入操作更为复杂一些。删除操作步骤如下:
  1). 如果待删除节点z的左孩子和右孩子节点其中一个不是nil节点,那么将y设为待删除节点z的后继节点,否则将y设为z。(y临时保存待删除节点)
  2). 如果y的左孩子不是nil节点,那么将y的左孩子赋给临时节点x,否则将y的右孩子赋给临时节点x。
  3). 如果y的父节点为NULL,那么将x设为root节点
  4). 将y节点从树上移除
  5). 如果z跟y不是同一个节点,那么将z的key设为y的key
  6). 如果y的颜色是黑色,那么需要调用delete-fix-up算法进行调整。
  一个黑色节点的删除会违反红黑树性质#5,因此需要调整,但是违反性质#5调整起来非常困难,我们可以假想节点x(就是在上面删除步骤中替代了y位置的节点)多出来一个黑色,这样的话x就变成要么两个黑色,要么一红一黑,这就是违反了性质#4了。但是毕竟x本身只有一种颜色,我们硬生生给它增加了另一种颜色,所以,这个新增加的颜色还是需要去除的,在满足下面三个条件后,新增加的颜色和去掉:x是根节点如果x是红黑复合节点,那么这个时候将x节点设为黑色即可经过适当的旋转和颜色调整后
  下面是delete-fix-up算法的步骤:
  1). 如果x不是根节点并且x的颜色是黑色的,那么重复下面的步骤:
  2). 如果x是它的父节点的左孩子那么将w设为x的兄弟节点如果x的父节点的右孩子是红色的:
  Case 1:将x父节点的右孩子设为黑色将x父节点设为红色对x的父节点执行左旋操作将x父节点的右孩子赋给w如果w的左孩子和右孩子都是黑色:
  Case 2:将w的颜色设为红色将x的父节点赋给x否则如果w的右孩子的颜色是黑色的:
  Case 3:将w左孩子的颜色设为黑色将w设为红色对w执行右旋操作将x父节点的右孩子赋给w如果上面的所有情形都没有发生,那么执行下面Case 4:
  Case 4:将w的颜色设为x父节点的颜色将x父节点的颜色设为黑色将w右孩子的颜色设为黑色对x执行左旋操作将x设为树的根节点
  3). 如果x是它的父节点右孩子,那么操作步骤与2)中描述相同,只是将其中的左孩子改为右孩子,将其中的右孩子改为左孩子即可。
  4). 将x的颜色设为黑色。
  上面介绍了红黑树的插入和删除操作。对于红黑树的遍历与二叉搜索树相同,这里不再介绍。对于上面提到的后继节点的求法,文中没有介绍,其实也比较简单,可以看我下面用C语言实现的红黑树的源码。希望本文对大家理解红黑树有所帮助。/* **   rbtree header file **   rbtree.h  **   author: 程序驱动世界 **   reversion: 1.0 **   2021/06/08 **/   #ifndef __RB_TREE_H__ #define __RB_TREE_H__  #ifdef __cplusplus     extern "C" { #endif  #include  #include  #include  #include   #define ASSERT(condition)  do{     if (condition){         NULL;     }else{         fflush(stdout); 		fprintf(stderr, "ASSERT failed: %s, line: %u ", __FILE__, __LINE__); 		fflush(stderr); 		abort();     } }while(0)   #define RB_RED     0 #define RB_BLACK   1  typedef uint32_t keytype;  struct  _rbtree_iterator{     keytype key; };  typedef struct  _rbtree_iterator*   rbtree_iterator_t; typedef struct rbnode rbnode_t; typedef struct rbtree retree_t;  struct rbtree * rbtree_create(); void rbtree_preorder_traversal(struct rbtree * tree); void rbtree_inorder_traversal(struct rbtree * tree); void rbtree_postorder_traversal(struct rbtree * tree); void rbtree_print(struct rbtree * tree); int32_t rbtree_exist(struct rbtree * tree, keytype key); rbtree_iterator_t rbtree_insert(struct rbtree * tree, keytype key); int32_t rbtree_delete(struct rbtree * tree, keytype key); void rbtree_destory(struct rbtree * tree); uint32_t rbtree_node_count(struct rbtree * tree); rbtree_iterator_t rbtree_begin(struct rbtree * tree); rbtree_iterator_t rbtree_end(struct rbtree * tree); rbtree_iterator_t rbtree_next(struct rbtree * tree, struct _rbtree_iterator * iter);   #ifdef __cplusplus     } #endif  #endif // __RB_TREE_H__/* **   rbtree c file **   rbtree.c  **   author: 程序驱动世界 **   reversion: 1.0 **   2021/06/08 **/   #include  #include  #include  #include  #include "rbtree.h"   struct rbnode{     struct rbnode * parent;     struct rbnode * lchild;     struct rbnode * rchild;     uint8_t color;     struct  _rbtree_iterator rbiter; };   struct rbtree{     uint32_t node_count;     struct rbnode * root;     struct rbnode * nil; };   /**  *         |                      |  *         x                      y  *        /        ---->        /   *       a   y                  x   c  *          /                 /   *         b   c              a   b **/ static void rbtree_left_rotate(struct rbtree * tree, struct rbnode *x){     struct rbnode * y = x->rchild;        // set y to the x right child     x->rchild = y->lchild;                // set the right child of x to the left child of y     y->lchild->parent = x;                // set the parent of left child of y to x      y->parent = x->parent;                // set the parent of y to the parent of x      if (!x->parent){                      // if the parent of x is NULL, set the y as tree node         tree->root = y;     }else if (x == x->parent->lchild){    // if x is the left child of its parent         x->parent->lchild = y;            // set the left child of x"s parent to y     }else{                                // if x is the right child of its parent         x->parent->rchild = y;            // set the right child of x"s parent to y         }      y->lchild = x;                        // set the left child of y to x     x->parent = y;                        // set the parent of x to y }    /**  *            |                       |  *            y                       x  *           /       <----          /   *          a    x                  y   c  *              /                 /   *             b   c              a   b  **/ static void rbtree_right_rotate(struct rbtree * tree, struct rbnode *x){     struct rbnode * y = x->lchild;     // set y to x left child     x->lchild = y->rchild;             // set the left child of x to the right child of y     y->rchild->parent = x;             // set the parent of y"s right child to x     y->parent= x->parent;              // set the parent of y to the parent of x      if(!x->parent){                    // if the parent of x is NULL, set y as tree bode         tree->root = y;     }else if(x == x->parent->rchild){  // if x is the right child of its parent         x->parent->rchild = y;         // set y as the right child of x"s parent     }else{                             // if x is the left child of its parent         x->parent->lchild = y;         // set the left child of x"s parent to y     }      y->rchild = x;                     // set the right child of y to x     x->parent = y;                     // set the parent of x to y }   static void rbtree_insert_fixup(struct rbtree * tree, struct rbnode * z){     //Case 2: the color of the parent of the current node is BLACK     if(z->parent->color == RB_BLACK){         return;                         // Do not need to fixup     }      //Case 3: the color of the parent of the current node is RED     struct rbnode * y = tree->nil;     while(z->parent && z->parent->color == RB_RED){         if (z->parent == z->parent->parent->lchild){   // node"s parent is node"s grandparent"s left child             y = z->parent->parent->rchild;              if (y && y->color == RB_RED){                //Case 3.1 the color of the uncle node of the current node is RED                 z->parent->color = RB_BLACK;                // set the color of current node"s parent to BLACK                 y->color = RB_BLACK;                         // set the uncle"s color to BLACK                 z->parent->parent->color = RB_RED;           // set the color of grandparent to RED                 z = z->parent->parent;                       // set the current node to grandparent                 continue;              }else if(z == z->parent->rchild){            //Case3.2 the color of the uncle node is BLACK and the current node is the right child of its parent                 z = z->parent;                               //set the current node to its parent                 rbtree_left_rotate(tree, z);                 // left rotate             }              z->parent->color = RB_BLACK;                 //Case3.3 the color of the uncle node is BLACK, and the current node is the left child of its parent             z->parent->parent->color = RB_RED;               // set the grandparent"s color to RED             rbtree_right_rotate(tree, z->parent->parent);    // right rotate with grandparent as the pivot         }else{             y = z->parent->parent->lchild;              if (y && y->color == RB_RED){                //Case 3.1 the color of the uncle node of the current node is RED                 z->parent->color = RB_BLACK;                // set the color of current node"s parent to BLACK                 y->color = RB_BLACK;                         // set the uncle"s color to BLACK                 z->parent->parent->color = RB_RED;           // set the color of grandparent to RED                 z = z->parent->parent;                       // set the current node to grandparent                 continue;              }else if(z == z->parent->lchild){            //Case3.2 the color of the uncle node is BLACK and the current node is the left child of its parent                 z = z->parent;                               //set the current node to its parent                 rbtree_right_rotate(tree, z);                // left rotate             }              z->parent->color = RB_BLACK;                 //Case3.3 the color of the uncle node is BLACK, and the current node is the left child of its parent             z->parent->parent->color = RB_RED;               // set the grandparent"s color to RED             rbtree_left_rotate(tree, z->parent->parent);     // right rotate with grandparent as the pivot         }     }      tree->root->color = RB_BLACK; }   static void rbtree_insert_impl(struct rbtree * tree, struct rbnode * z){     ASSERT(tree != NULL && z !=NULL);          //Case 1: The tree node is nil, just set the tree node to node     // And marked its color to black.     if(tree->root == tree->nil){         tree->root = z;         tree->root->color = RB_BLACK;         tree->node_count += 1;         return;     }      struct rbnode * x = tree->root;     struct rbnode * y = tree->nil;     while (x != tree->nil){         y = x;         if (z->rbiter.key < x->rbiter.key){             x = x->lchild;         }else{             x = x->rchild;         }     }      z->parent = y;     if(z->rbiter.key < y->rbiter.key){         y->lchild = z;     }else{         y->rchild = z;     }      z->lchild = tree->nil;     z->rchild = tree->nil;      z->color = RB_RED;      rbtree_insert_fixup(tree, z);     tree->node_count += 1; }   static struct rbnode * rbtree_minimum(struct rbtree * tree, struct rbnode * x){     ASSERT(tree!=NULL);      struct rbnode * node = x;      if (!node){         return tree->nil;     }      while (node->lchild != tree->nil) {         node = node->lchild;     }      return node;     }   static struct rbnode * rbtree_maximum(struct rbtree * tree, struct rbnode * x){     ASSERT(tree!=NULL);      struct rbnode * node = x;      if(!node){         return tree->nil;     }      while (node->rchild != tree->nil) {         node = node->rchild;     }      return node; }   static struct rbnode * rbtree_successor(struct rbtree * tree, struct rbnode * x) {     ASSERT(tree != NULL && x != NULL);      if (x->rchild != tree->nil){         return rbtree_minimum(tree, x->rchild);     }      struct rbnode * y = x->parent;      while (y && y != tree->nil && x == y->rchild) {         x = y;         y = y ->parent;      }          if(!y){         return tree->nil;     }      return y; }   static struct rbnode * rbtree_predecessor(struct rbtree * tree, struct rbnode * x){     ASSERT(tree != NULL && x != NULL);          if(x->lchild != tree->nil){         return rbtree_maximum(tree, x->lchild);     }      struct rbnode * y = x->parent;      while(y && y != tree->nil && x == y->rchild){         x = y;         y = y->parent;     }      if(!y){         return tree->nil;     }      return y; }   static void rbtree_delete_fixup(struct rbtree * tree, struct rbnode * x){     struct rbnode * w = tree->nil;      while (x != tree->root && x->color == RB_BLACK){                    // x"s color is BLACK and x is not the root of the tree         if (x == x->parent->lchild){                                               w = x->parent->rchild;                                      // if x is the left child of its parent, set the w as x"s sibling child             if (w->color == RB_RED){                                    // Case 1: x"s sibling color is RED, so x"sparent and w"s childs are all BLACK                 w->color = RB_BLACK;                                    //   1), set x"s sibling node to BLACK                 x->parent->color = RB_RED;                              //   2), set x"s parent color to RED                 rbtree_left_rotate(tree, x->parent);                    //   3), do the left rotation with x"s parent as pivot                 w = x->parent->rchild;                                  //   4), reset the x"s sibling node after the rotation              }else if(w->lchild->color == RB_BLACK &&                       w->rchild->color == RB_BLACK){                     // Case 2: x"s sibling color is BLACK, and the children of x"s sibling are all BLACK                 w->color = RB_RED;                                      //    1), set the sibling node color to RED                 x = x->parent;                                          //    2), set the x equal to its parent              }else {                 if(w->rchild->color == RB_BLACK){                     // Case 3: x"s sibling color is BLACK, and the right child of w is BLACK while its left child is RED                     w->lchild->color = RB_BLACK;                            //    1), set the left child of w to BLACK                     w->color = RB_RED;                                      //    2), set the w"s colot to RED                     rbtree_right_rotate(tree, w);                           //    3), do the rotation with w as pivot                     w = x->parent->rchild;                                  //    4), reset the sibling node after rotation                 }                  w->color = x->parent->color;                          // Case 4: x"s sibling color is BLACK, the right child of w is RED, 1), set the parent color to w                 x->parent->color = RB_BLACK;                                //    2), set x"parent color to BLACK                 w->rchild->color = RB_BLACK;                                //    3), set the color of right child of sibling node to BLACK                 rbtree_left_rotate(tree, x->parent);                        //    4), do the rotation with x"parent as pivot                 x = tree->root;                                             //    5), set x as root node of the tree             }                                                                                     }else{             w = x->parent->lchild;                                      // if x is the right child of its parent, set the w as x"s sibling child             if (w->color == RB_RED){                                    // Case 1: x"s sibling color is RED, so x"sparent and w"s childs are all BLACK                 w->color = RB_BLACK;                                    //   1), set x"s sibling node to BLACK                 x->parent->color = RB_RED;                              //   2), set x"s parent color to RED                 rbtree_right_rotate(tree, x->parent);                   //   3), do the right rotation with x"s parent as pivot                 w = x->parent->lchild;                                  //   4), reset the x"s sibling node after the rotation              }else if(w->rchild->color == RB_BLACK &&                       w->lchild->color == RB_BLACK){                     // Case 2: x"s sibling color is BLACK, and the children of x"s sibling are all BLACK                 w->color = RB_RED;                                      //    1), set the sibling node color to RED                 x = x->parent;                                          //    2), set the x equal to its parent              }else {                                                   // Case 3: x"s sibling color is BLACK, and the left child of w is BLACK while its right child is RED                 if(w->lchild->color == RB_BLACK){                     w->rchild->color = RB_BLACK;                            //    1), set the right child of w to BLACK                     w->color = RB_RED;                                      //    2), set the w"s colot to RED                     rbtree_left_rotate(tree, w);                            //    3), do the rotation with w as pivot                     w = x->parent->lchild;                                  //    4), reset the sibling node after rotation                 }                  w->color = x->parent->color;                                // Case 4: x"s sibling color is BLACK, the left child of w is RED, 1), set the parent color to w                 x->parent->color = RB_BLACK;                                //    2), set x"parent color to BLACK                 w->lchild->color = RB_BLACK;                                //    3), set the color of left child of sibling node to BLACK                 rbtree_right_rotate(tree, x->parent);                       //    4), do the rotation with x"parent as pivot                 x = tree->root;                                             //    5), set x as root node of the tree             }         }     }          x->color = RB_BLACK;                                               // set the color of x to BLACK                          }   static struct rbnode * rbtree_delete_impl(struct rbtree * tree, struct rbnode * z){     ASSERT(tree != NULL && z !=NULL);      struct rbnode * y = tree->nil;     struct rbnode * x = tree->nil;      if(z->lchild == tree->nil && z->rchild == tree->nil){   // the left and right child of the z is nil, leaf node         y = z;                                      // set y to z      }else{                       y = rbtree_successor(tree, z);              // set y to the z"s successor node                   }          if (y->lchild != tree->nil){                   // if the left child of y is not nil then set x equal to y"s left child         x = y->lchild;      }else{         x = y->rchild;                              // otherwise set the right child of y to x     }      x->parent = y->parent;                          // set the parent of y to the parent of x      if (y->parent == NULL){                         // the parent of y is NULL, so set x as tree node         tree->root = x;      }else if (y == y->parent->lchild){              // if y is its parent"s left child, set x as the left child of y"s parent         y->parent->lchild = x;      }else{         y->parent->rchild = x;                      // set x as the right child of y"s parent      }      if (y != z){                                    // if y is not equal to z         z->rbiter.key = y->rbiter.key;              // copy the key of y to the key of z, here we won"t change the color     }      if (y->color == RB_BLACK){          rbtree_delete_fixup(tree, x);               // if the color of y is BLACK, then need to fixup x      }      tree->node_count -= 1;      return y; }   static void rbtree_preorder_traversal_impl(struct rbtree * tree, struct rbnode * node){     ASSERT(node != NULL);      if (node != tree->nil){         printf("%ld ", node->rbiter.key);          rbtree_preorder_traversal_impl(tree, node->lchild);         rbtree_preorder_traversal_impl(tree, node->rchild);     }     }   static void rbtree_inorder_traversal_impl(struct rbtree * tree, struct rbnode * node){     ASSERT(node != NULL);      if (node != tree->nil){         rbtree_inorder_traversal_impl(tree, node->lchild);          printf("%ld ", node->rbiter.key);          rbtree_inorder_traversal_impl(tree, node->rchild);     } }   static void rbtree_postorder_traversal_impl(struct rbtree * tree, struct rbnode * node){     ASSERT(tree!=NULL && node != NULL);      if (node != tree->nil){         rbtree_postorder_traversal_impl(tree, node->lchild);         rbtree_postorder_traversal_impl(tree, node->rchild);          printf("%ld ", node->rbiter.key);      } }  #define SPACE_COUNT  10 static void rbtree_print_impl(struct rbtree * tree, struct rbnode * node, int space){ 	if (tree == NULL) { 		return; 	}  	space += SPACE_COUNT;  	if (node == tree->nil) { 		for (int i = SPACE_COUNT; i < space; i++) { 			printf(" "); 		} 		printf("%s:%s ", "nil", "black"); 		return; 	}  	rbtree_print_impl(tree, node->rchild, space);  	printf(" "); 	for (int i = SPACE_COUNT; i < space; i++) { 		printf(" "); 	} 	printf("%ld:%s ", node->rbiter.key, node->color == RB_RED ? "red" : "black");  	rbtree_print_impl(tree, node->lchild, space); }   static struct rbnode * rbtree_search(struct rbtree *tree, keytype key){     struct rbnode * node = tree->root;     while(node != tree->nil && node->rbiter.key != key){         if (key < node->rbiter.key){             node = node->lchild;         }else{             node = node->rchild;         }     }      return node; }   static struct rbnode * rbtree_create_node(struct rbtree * tree, keytype key){     struct rbnode * node = (struct rbnode *)malloc(sizeof(struct rbnode));     if(!node){         return tree->nil;     }          node->rbiter.key = key;     node->lchild = tree->nil;     node->rchild = tree->nil;     node->parent = NULL;     node->color = RB_BLACK;      return node; }   static void rbtree_destroy_impl(struct rbtree * tree, struct rbnode * node){      if (node == tree->nil){         return;     }      if (node->lchild != tree->nil){         rbtree_destroy_impl(tree, node->lchild);     }      if (node->rchild != tree->nil){         rbtree_destroy_impl(tree, node->rchild);     }      free(node); }  struct rbtree * rbtree_create(){     struct rbtree * tree = (struct rbtree * )malloc(sizeof(struct rbtree));     ASSERT(tree != NULL);     tree->nil = (struct rbnode *)malloc(sizeof(struct rbnode));     ASSERT(tree->nil != NULL);      tree->nil->lchild       = NULL;     tree->nil->rchild       = NULL;     tree->nil->parent       = NULL;     tree->nil->color        = RB_BLACK;      tree->root = tree->nil;     tree->node_count = 0;      return tree; }   void rbtree_preorder_traversal(struct rbtree * tree){     rbtree_preorder_traversal_impl(tree, tree->root); }   void rbtree_inorder_traversal(struct rbtree * tree){     rbtree_inorder_traversal_impl(tree, tree->root); }   void rbtree_postorder_traversal(struct rbtree * tree){     rbtree_postorder_traversal_impl(tree, tree->root); }   void rbtree_print(struct rbtree *tree){     ASSERT(tree!=NULL);      rbtree_print_impl(tree, tree->root, 0); }   int32_t rbtree_exist(struct rbtree * tree, keytype key){     ASSERT(tree != NULL);      if (tree->root != tree->nil){         return rbtree_search(tree, key) ? 0 : -1;     }      return -1; }   rbtree_iterator_t rbtree_insert(struct rbtree * tree, keytype key){     ASSERT(tree != NULL);      struct rbnode * fnode = rbtree_search(tree, key);      if(rbtree_search(tree, key) != tree->nil){    // key already exist.         return &fnode->rbiter;                                               }      struct rbnode * node = rbtree_create_node(tree, key);      if (node != tree->nil){         rbtree_insert_impl(tree, node);         return &node->rbiter;     }      return 0;                                             // error occurred }   int32_t rbtree_delete(struct rbtree * tree, keytype key){     ASSERT(tree != NULL);      struct rbnode * node = rbtree_search(tree, key);     if( node == tree->nil){         return -1;                                        // does not exist     }      node = rbtree_delete_impl(tree, node);      free(node);     return 0; }   void rbtree_destory(struct rbtree * tree){     ASSERT(tree != NULL);      struct rbnode *node = tree->root;      rbtree_destroy_impl(tree, tree->root);          free(tree->nil);     free(tree); }   uint32_t rbtree_node_count(struct rbtree * tree){     ASSERT(tree != NULL);      return tree->node_count; }   rbtree_iterator_t rbtree_begin(struct rbtree * tree){     ASSERT(tree != NULL);      struct rbnode * node = rbtree_minimum(tree, tree->root);     if (node == tree->nil){         return NULL;     }      return &node->rbiter; }   rbtree_iterator_t rbtree_end(struct rbtree * tree){     return NULL; }   rbtree_iterator_t rbtree_next(struct rbtree * tree, struct _rbtree_iterator * iter){     ASSERT(tree !=NULL);      if (!iter){         return NULL;     }      struct rbnode * x = (struct rbnode *)(((char *)iter) - ((size_t)&(((struct rbnode *)0)->rbiter)));     struct rbnode * node = rbtree_successor(tree, x);     if (node == tree->nil){         return NULL;     }      return &node->rbiter; }

男友家境远不及我,还要补贴原生家庭买房,我该如何应对不吃亏?我是小透明男朋友家境不好的话还要继续谈下去吗?我跟我男朋友是大学的同学,到现在为止也谈了5个年头了。我先说一下自己的情况,家里在一线城市和二线城市都有一套房产,无贷款,本科学历,目父母有这四种行为不仅是溺爱也是对孩子的伤害有题主问孩子的成长是不是就是需要磕磕绊绊的呢,如果家长过分的溺爱孩子的话会有什么影响呢?你好!我是心融有道平台的Lisa。溺爱是照顾者和儿童之间的关系的一种特征,溺爱即不公正的物质痛心!爸爸举高高将儿子摔进ICU,医生都只能无奈摇头童年的回忆总是很美好的,很多家长喜欢拉着孩子的手荡秋千,也有人喜欢把孩子举高高,因为这样能够逗孩子笑。而很多人并不知道,举高高是很危险的事情,最近有一个婴儿被爸爸举高高然后摔到地上特朗普对脸书推特和YouTube社交媒体巨头提起诉讼据美国彭博社报道,美国前总统特朗普当地时间10月1日要求美国佛罗里达州迈阿密一名联邦法官强迫社交媒体平台推特公司恢复自己的推特账号。彭博社报道截图报道称,特朗普的律师在一份文件中指迷惑发言?杜发文称姚策不像她,网友两人简直一个模子印出来最近,熊磊的儿子楷楷过生日,奶奶杜新枝也献上了祝福,同时她也在平台发布了文章,内容让人惊叹不已。她表示自己的儿子姚策跟自己不像,像自己的女儿。这话一说出,网友坐不住了,天下哪有这样熊磊刚开网店就开始刷单?怪不得之前跟北海舅舅闹矛盾如果从事过电商行业的人,一定对刷单的词汇不陌生。而现在,熊磊的网店才刚开张,就被人曝光进行了刷单操作,根本就没有这么多订单。网友感叹,当初熊磊是多么嚣张,现在却是这个下场。有人在熊上海长宁独居女孩遭杀害被藏行李箱后抛尸,更多案发细节曝光继江西吉安市女孩遭上司杀害,尸体藏于行李箱后抛尸,近日上海长宁又发生一起行李箱藏尸案,一名独居女孩被杀害后,遭到嫌疑人将尸体藏于行李箱,并将其运走抛弃。目前,视频中拉着行李箱走出小上海一小区加装电梯,一楼住户竟毫不知情谁给我签的名?随着电梯房越来越受欢迎,老旧小区的改造也跟随着潮流的脚步,为了楼梯房住户出行更加的便捷,老小区安装外部电梯有不少的补贴,这对于住在稍微高楼层的住户来说简直不要太好,但要真的是实行起抠门女子毕业9年买两套房从小母亲把零花钱扔在地上,让她捡时下,楼价趋向稳定的阶段,但买房子并不是说买就能买,尤其对于大部分年轻人来说,这几乎是一件遥不可及事情,但对于南京一名32岁的女子来说,这并不是件困难的事情。毕业9年的她靠着抠,在杜新枝是无辜的?金果儿许敏哥哥找到了偷孩子的人,不是她金果儿事件一出,人们都震惊了!这个年代竟然还有地头蛇,还是这么嚣张!如果金果儿没有人给她撑腰,相信是不会这么无法无天的。而这次,她给出了一个惊人的消息,那就是许敏的哥哥已经找到了偷13岁女孩失联多天,母亲跪在男方家门口痛哭求你把女儿还我对于父母而言,孩子的事永远都是天大的事,父母都害怕自己的子女在成长过程中遭到意外,但子女大了不由娘,孩子长大了自然会有自己的自主意识,叛逆的心理就此萌发,这是父母最为担心受怕的,就
年度最佳跑车之2021款保时捷718Cayman2021款保时捷718Cayman优点超凡的驾驶特性,两种变速箱都是完美,丰富的个性化选择。缺点机舱缺乏便利的存储点,四缸噪音比其他同行要贵。结论它可能是世界上最实惠的超级跑车。总年度最佳跑车之2021款雪佛兰Corvette2021款雪佛兰Corvette优点出色的性能与异国情调的汽车相媲美,舒适到愿意每天驾驶的精美座舱。缺点只有在全油门,有限的驾驶员辅助功能,不提供手动变速箱的情况下,排气才会令人兴年度最佳跑车之2021款保时捷718Boxster2021款保时捷718Boxster优点干脆的处理,急切的动力总成,自由风行。缺点精致的四缸噪音,缺乏存储空间,沉闷的座舱。结论尽管718Boxster有很多缺点,但令人兴奋的驾驶年度最佳轿车之2020款梅赛德斯AMGS63S652020款梅赛德斯AMGS63S65优点精心打造的座舱,快速加速,精致的操控性。缺点货运空间比竞争对手的轿车少,燃油效率比某些竞争对手低,底价比某些竞争对手高。结论S63和S65拥年度最佳跑车之2021款宝马M2优点喧闹而精致的发动机,满足驾驶特性,仍然提供自行换挡的变速器。缺点内饰缺乏M2价格的束缚,僵硬的行驶,更纤薄,动力更弱的M240i更物有所值。结论M2是出色的驾驶者的汽车,但对于年度最佳轿车之2020款梅赛德斯奔驰E级2020款梅赛德斯奔驰E级总览在某种程度上,E级轿车是梅赛德斯奔驰S级轿车的打折版本,这是一件好事。它具有与Benz旗舰轿车相同的抛光度和光泽度,并具有出色的内饰材料,安静的驾驶舱华为MateX2畅连APP有多香?全新的分享方式你会吗?2月22日晚间,华为新一代折叠旗舰手机MateX2正式发布,从设计到适配都达到了全新高度,刷新了我们对折叠屏手机的期待。搭载MateX2拖拽分享多应用分屏悬浮窗口等功能,畅连APP年度最佳轿跑车之2021款福特野马2021款福特野马优点所有型号的驾驶都乐趣无穷,座舱比Camaro的宽敞,性能出色。缺点座舱有一些低于标准的装饰件,可用的Recaro座椅过于激进,标准的四缸太柔和了。结论野马将形年度最佳轿车之2020款马自达32020款马自达3市场上最经典的紧凑型汽车体验之一。总览马3凭借全面的完善和先进的驾驶方式,是同类产品中最好的紧凑型汽车之一。马自达可作为掀背车或轿车提供,是本田思域和丰田卡罗拉等年度最佳轿车之2020款马自达62021款马自达6优点比竞争对手更经典,更出色的操控性,更安静的机舱。缺点涡轮发动机缺乏魅力,缺少环保型车型,为最贵的内饰级别预留了顶级选装件。结论马自达6是一款出色的家用轿车,因年度最佳SUV和跨界车之2021款宝马X32021宝马X3优点优美的行驶动力,强大的可选发动机,出众的燃油经济性。缺点微小的外后视镜无助于盲点,不完善的自动停止启动行为,过时的室内设计。结论X3是为渴望一些老式宝马驾驶技术