红黑树定义和性质

红黑树是一种含有红黑结点并能自平衡的二叉查找树。它必须满足下面性质:

  • 性质1:每个节点要么是黑色,要么是红色。
  • 性质2:根节点是黑色。
  • 性质3:每个叶子节点(NIL)是黑色。(这里的叶子节点是指空叶子节点)
  • 性质4:每个红色结点的两个子结点一定都是黑色。
  • 性质5:任意一结点到每个叶子结点的路径都包含数量相同的黑结点。


红黑树是一棵近似平衡的二叉搜索树,它查找、插入和删除的时间复杂度都是O(lg n);

红黑树的自平衡

插入和删除会破坏红黑树的平衡,需要靠三种操作来维持:左旋、右旋和变色。旋转的时候维持二叉搜索树的性质就好(左子结点比根节点小,右子节点比根节点大

左旋和右旋的意义就是让违反性质4的节点不断上移到根节点,然后让根节点变成黑色(避免违反性质5),这样就可以达到自平衡

 

  • 左旋:对x进行左旋,意味着,将“x的右孩子”设为“x的父亲节点”;即,将 x变成了一个左节点(x成了为z的左孩子)!。 因此,左旋中的“左”,意味着“被旋转的节点将变成一个左节点”

  左旋示例图(以x为节点进行左旋):

                               z
   x                          /                  
  / \      --(左旋)-->       x
 y   z                      /
                           y

 

   

/*
 * 左旋示意图(对节点x进行左旋):
 *
 *
 *      px                              px
 *     /                               /
 *    x                               y
 *   /  \      --(左旋)-->           / \                #
 *  lx   y                          x  ry
 *     /   \                       /  \
 *    ly   ry                     lx  ly
 *
 * 三处变化:
 * 1、被旋转的节点  变成  左节点
 * 2、被旋转节点的右节点  变成  根节点
 * 3、被旋转节点的右节点的左节点  变成  被旋转节点的右节点
 *
 * 代码实现的时候,修改这种变化从第3点开始修改(也就是最下面的变化开始往上修改)
 */

 //以x为支点进行左旋
void LeftRotate(Tree* tree, node* x)
{
    //新建节点y,保存x的右节点
    node* y = x->right;

    //将被旋转节点的右节点的左节点  设置为  被旋转节点的右节点
    x->right = y->left;

    //更新被旋转节点x的  右节点的左节点  的父节点
    if (y->left != NULL)
        y->left->parent = x;

    //更新旋转后  y的父节点
    y->parent = x->parent;

    //判断x为根节点的情况,那么旋转后y变成根节点
    if (x->parent == NULL)
        tree->root = y;
    else
    {
        //如果x是它父节点的左儿子,旋转后这个父节点的左儿子就是y
        if (x == x->parent->left)
            x->parent->left = y;
        else
            x->parent->right = y;
    }

    y->left = x;
    x->parent = y;

}
左旋(LeftRotate)

 

 

 

  • 右旋:对x进行右旋,意味着,将“x的左孩子”设为“x的父亲节点”;即,将 x变成了一个右节点(x成了为y的右孩子)! 因此,右旋中的“右”,意味着“被旋转的节点将变成一个右节点”

  右旋示例图(以x为节点进行右旋):

                             y
   x                            \                 
  / \      --(右旋)-->           x
 y   z                            \
                                   z

  

 

/*
 * 右旋示意图(对节点y进行左旋):
 *
 *
 *            py                               py
 *           /                                /
 *          y                                x
 *         /  \      --(右旋)-->            /  \                     #
 *        x   ry                           lx   y
 *       / \                                   / \                   #
 *      lx  rx                                rx  ry
 *
 * 三处变化:
 * 1、被旋转的节点  变成  右节点
 * 2、被旋转节点的左节点  变成  根节点
 * 3、被旋转节点的左节点的右节点  变成  被旋转节点的左节点
 */

 //以y为支点进行左旋
void RightRotate(Tree* tree, node* y)
{
    //新建x节点保存被旋转节点的左节点
    node* x = y->left;

    //将被旋转节点的左节点的右节点  设置为  被旋转节点的左节点
    y->left = x->right;

    //更新被旋转节点y的  左节点的右节点  的父节点
    if (x->right != NULL)
        x->right->parent = y;

    //更新旋转后  x的父节点
    x->parent = y->parent;

    //判断y为根节点的情况,那么旋转后x变成根节点
    if (y->parent == NULL)
        tree->root = x;
    else
    {
        //如果被旋转节点y是它父节点的左儿子,旋转后这个父节点的左儿子就是x
        if (y == y->parent->right)
            y->parent->right = x;
        else
            y->parent->left = x;
    }

    x->right = y;
    y->parent = x;

}
右旋(RightRotate)

 

 

 

  • 变色:结点的颜色由红变黑或由黑变红。

相关文章: