当前位置:   article > 正文

判断是否为红黑树

判断是否为红黑树

目录

红黑树条件        

结点定义

判断方式

判断根的颜色是否为黑

判断红结点的子结点

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

实现

经验总结

红黑树条件        

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

结点定义

  1. typedef struct RBTnode
  2. {
  3. int data;
  4. bool color; // 0 for black, 1 for red
  5. RBTnode *lchild, *rchild;
  6. int left, right, it;
  7. } * 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的情况,也就是处理顺序为->,按照什么顺序能刚好把一棵树按照子->父的顺序遍历一遍呢,刚好是后序(左右根)。

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

实现

  1. void No()
  2. {
  3. system("cls");
  4. printf("No\n");
  5. exit(0);
  6. }
  7. void judge(node x)
  8. {
  9. if (x->color) //根为红
  10. No();
  11. post_order_t(x);
  12. system("cls");
  13. printf("Yes\n");
  14. }
  15. void post_order_t(node x)
  16. {
  17. if (!x)
  18. return;
  19. post_order_t(x->lchild);//左
  20. post_order_t(x->rchild);//右
  21. //判断红色节点的子节点是否为黑
  22. if (x->color)
  23. {
  24. if (x->rchild)
  25. if (x->rchild->color)
  26. No();
  27. if (x->lchild)
  28. if (x->lchild->color)
  29. No();
  30. }
  31. //判断左右有几黑
  32. if (x->lchild)
  33. x->left = (x->lchild->it);
  34. else
  35. x->left = 1;
  36. if (x->rchild)
  37. x->right = (x->rchild->it);
  38. else
  39. x->right = 1;
  40. if (x->left == x->right)
  41. x->it += x->left;
  42. else
  43. No();
  44. }

经验总结

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

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

  1. //判断红色节点的子节点是否为黑
  2. if (x->color)
  3. {
  4. if (x->rchild)
  5. if (x->rchild->color)
  6. No();
  7. if (x->lchild)
  8. if (x->lchild->color)
  9. No();
  10. }

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/246176?site
推荐阅读
相关标签
  

闽ICP备14008679号