Is It A Red-Black Tree?(判断一棵树是否为红黑二叉树)

以前没接触过这种树,看了别人的代码,加上了详细的注释。

思路全在注释中。

 

简单把红黑树的五条性质翻译下:

1.每个节点只有两种颜色:非红即黑;

2.根节点是黑色;

3.叶子节点(NULL)是黑色的(对于每个叶子节点来说,他的左右孩子(NULL)都是黑的)

4.若节点为红色,他的所有孩子都是黑色;

5.对于每个节点,从这个节点到每个叶子节点的黑色节点的个数都相同。

 

我将测试样例放上,以便复制。

3
9
7 -2 1 5 -4 -11 8 14 -15
9
11 -2 1 -7 5 -4 8 14 -15
8
10 -7 5 -6 8 15 -11 17

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 bool isRBTree = true;//默认所有的树全为红黑树
  5 int lastNum = -1;//这个是第五点,因为要比较树的不同分支上黑节点的个数,所以要记录上一个树黑点的个数,
  6 //但是第一次记录时是没有上一个树的数据的,所以要去判断是不是第一次记录,用初始化为-1的方式来标记
  7 
  8 struct Node
  9 {
 10     int data;
 11     bool isblack;//是否为黑点
 12     Node *lchild ;//左右孩子默认都为空
 13     Node *rchild;
 14 
 15     void setData(int mdata)
 16     {
 17         if (mdata > 0)//如果数据大于0
 18         {
 19             isblack = true;//
 20         }
 21         else
 22             isblack = false;//否则为红
 23         data = abs(mdata);//将绝对值存入,因为红黑已经记录,符号已经没有意义
 24     }
 25 };
 26 
 27 Node *Insert(int a, Node *root)
 28 {
 29     if (root == NULL)//如果为空
 30     {
 31         root = (Node *)malloc(sizeof(Node));
 32         root->lchild = NULL;//设置节点的左右孩子为null
 33         root->rchild = NULL;
 34         root->setData(a);
 35         return root;
 36     }
 37     if (abs(a) < root->data)//红黑树的左孩子一定比父亲小
 38     {
 39         root->lchild = Insert(a, root->lchild);//插入
 40     }
 41     else                  //右孩子一定比父亲大
 42         root->rchild = Insert(a, root->rchild);
 43     return root;
 44 }
 45 
 46 void DFS(Node *node, int count)
 47 {
 48     if (!isRBTree)//如果已经判断出不是红黑树
 49     {
 50         return;//退出
 51     }
 52     if (node == NULL)//如果是空节点有两种情况
 53     {
 54         if (lastNum == -1)//一种是还没进行第一次遍历
 55         {
 56             lastNum = count;//那么就要将计数器归零,也就是在main里面传进来的0
 57         }
 58         else if (lastNum != count)//如果是已经遍历到叶子结点,
 59                                     //换句话说就是节点的左孩子或者右孩子为空
 60         {
 61             isRBTree = false;//因为本次遍历与上次遍历的黑节点数不同,不符合第五点
 62                                 //所以返回假
 63         }
 64         return;//遍历到终点,结束遍历
 65     }
 66     if (node->isblack)//如果这个点是黑节点
 67     {
 68         count++;
 69     }
 70     else
 71     {
 72         if (node->lchild && !node->rchild->isblack)//左孩子存在并且他的左孩子是红的,第4点
 73             isRBTree = false;//为假
 74         if (node->rchild && !node->rchild->isblack)//同理
 75             isRBTree = false;
 76     }
 77     DFS(node->lchild, count);//深度搜索左孩子
 78     DFS(node->rchild, count);
 79 
 80 }
 81 
 82 int main()
 83 {
 84     int num;
 85     scanf("%d", &num);
 86     bool answer[33];//将答案存在数组中
 87     int i, j;
 88     for (i = 0; i < num; i++)
 89     {
 90         int number;
 91         scanf("%d", &number);
 92         Node *root = NULL;
 93         int a;
 94         for (j = 0; j < number; j++)
 95         {
 96             scanf("%d", &a);
 97             root = Insert(a, root);
 98         }
 99         isRBTree = root->isblack;//条件2
100         lastNum = -1;//好多样例,记得初始化
101         DFS(root, 0);
102         answer[i] = isRBTree;
103         isRBTree = true;//初始化,和上面一样
104     }
105     for (i = 0; i < num; i++)
106     {
107         if (answer[i])
108             printf("Yes\n");
109         else
110             printf("No\n");
111     }
112 }

 

转载于:https://www.cnblogs.com/KangYh/p/9997121.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值