判断是否为红黑树

目录

红黑树条件        

结点定义

判断方式

判断根的颜色是否为黑

判断红结点的子结点

判断任意结点到所有后代叶子是否包含相同数量的黑色结点

实现

经验总结

红黑树条件        

  1. 根为黑
  2. 红结点的子结点黑
  3. 对于每个结点,从该结点到后代叶子的所有简单路径都包含相同数量的黑色结点

结点定义

typedef struct RBTnode
{
	int data;
	bool color; // 0 for black, 1 for red
	RBTnode *lchild, *rchild;
	int left, right, it;
} * RBTree, Node, *node;

判断方式

  1. 判断根的颜色是否为黑

  2. 判断红结点的子结点颜色

    1. 通过任意顺序遍历一次,如果是红色,就判断子结点是否为黑色

  3. 判断任意结点到所有后代叶子是否包含相同数量的黑色结点

    1. 结构:
      对于每一个结点,加入三个数据:
      1. left:从左子到叶有多少个黑结点
      2. right:从右子到叶有多少个黑结点
      3. it:自己到叶有多少个黑结点
    2. 例子:
      以该树为例

        

      对于结点4

      左右子树到叶均有一个黑(leftright1)

      自己为红(it等于leftright等于1)

      对于结点5

      左右子树到叶均有一个黑(leftright1)

      自己为黑(it等于leftright加一,等于2)

      对于结点1

      左右子树到叶均有一个黑(leftright1)

      自己为黑(it等于leftright加一,等于2)

      对于结点2

      左右子树到叶均有两个黑(leftright2)

      自己为红(it等于leftright等于2)

  4.  规律
    1. 每一个结点如果有左子树,那么他的的left等于他lchildit,如果没有左子树,那么他的left等于1(NULL为黑)
      每一个结点如果有右子树,那么他的的right等于他rchildit,如果没有右子树,那么他的right等于1(NULL为黑)
    2. 如果一个结点的leftright相等
             每一个红结点的it等于他的leftright
             每一个黑节点的it等于他的(leftright)+1
      如果一个结点的leftright不相等
             说明不是红黑树
    3. 由1)和2)可以发现,在处理每一个结点的时候,需要先了解他的lchildrchild的情况,也就是处理顺序为->,按照什么顺序能刚好把一棵树按照子->父的顺序遍历一遍呢,刚好是后序(左右根)。

综上所述,只需要先判断根是否为黑,再后序遍历一遍,即可判断是否为红黑树

实现

void No()
{
    system("cls");
    printf("No\n");
    exit(0);
}

void judge(node x)
{
    if (x->color) //根为红
        No();
    post_order_t(x);
    system("cls");
    printf("Yes\n");
}

void post_order_t(node x)
{
    if (!x)
        return;
    post_order_t(x->lchild);//左
    post_order_t(x->rchild);//右

    //判断红色节点的子节点是否为黑
    if (x->color)
    {
        if (x->rchild)
            if (x->rchild->color)
                No();
        if (x->lchild)
            if (x->lchild->color)
                No();
    }

    //判断左右有几黑
    if (x->lchild)
        x->left = (x->lchild->it);
    else
        x->left = 1;
    if (x->rchild)
        x->right = (x->rchild->it);
    else
        x->right = 1;
    if (x->left == x->right)
        x->it += x->left;
    else
        No();
}

经验总结

首先要搞清楚,一共要判断哪些东西,比如,该题要先判断红结点的子结点颜色,可以用任意顺序遍历,但不用着急写实现。另一个在判断内容后,发现需要后序遍历,都研究好之后,可以用一次后序遍历处理掉所有问题。

其次是善于运用bool型变量,将10与实际需求联系起来,比如在判断红结点的子节点是否为黑时,更多需要的是判断某个结点是否为红

//判断红色节点的子节点是否为黑
if (x->color)
{
    if (x->rchild)
        if (x->rchild->color)
            No();
    if (x->lchild)
        if (x->lchild->color)
            No();
}

此时,1代表红,0代表黑就可以很好的利用起来

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值