PAT 1135 Is It A Red-Black Tree

根据给定的二叉搜索树,判断是否是红黑树。
符合红黑树的条件:
1.、节点是红色或黑色。
2、根节点是黑色。
3、 每个叶子节点(NULL节点,空节点)是黑色的。
4、 一个节点是红色,其左右子树为黑色
5、 对于树上任何节点来说,其左右子树的黑色节点个数是一样。
这里主要判断的条件有三个:
1、根是黑色(第二个测试点)
2、一个节点是红色,其左右子树为黑色。
3、对于树上任何节点来说,其左右子树的黑色节点个数是一样。
二叉搜索树左小右大,这一题可以直接根据这个性质和先序遍历的元素,重新进行先序遍历建立树,其实不需要建树,直接进行判断,根据父节点是否红色和当前节点是否红色判断是否符合条件;根据得到的左右子树的高度判断是否相同判断是否符合条件,右节点是当前节点找到第一个比当前节点大的节点。高度是黑色颜色的个数,如果是红色叶子节点,返回0,是黑色叶子节点返回1,然后根据每个节点的颜色从下到上处理。
这一题一开始题目理解错误,以为红黑树是从根节点出发每条路径的黑色节点个数的一样就行了。后来,改正后一直只有24分,第二个测试点总是通不过,搜索后发现别人说根节点要是黑色,修改后才通过,一直没有注意到这一点。
写过这一题,才算对红黑树有了一点的理解,它是用路径上的黑色节点个数当做高度,用于平衡。
(用时:2:05:15.26)

#include <bits/stdc++.h>
using namespace std;
const int RED = 0;
const int BLACK = 1;
bool isRBTree = true;
int bulidTree(int preOrder[],int currentIndex,int right,int fatherColor)
{
    if(right<=currentIndex) {
        return 0;
    }

    int currentColor = BLACK;
    if(preOrder[currentIndex]<0)  {
        currentColor = RED;
        if(fatherColor == RED) {
            isRBTree = false;
        }
    }


    int value = preOrder[currentIndex] < 0 ? -preOrder[currentIndex] :preOrder[currentIndex];
    int rightIndex = -1;
    int leftIndex = -1;
    for(int i=currentIndex+1; i<right; i++) {
        if(value < preOrder[i]||value < -preOrder[i]) {
            rightIndex = i;
            break;
        }
        //有相同值的,这里是默认当做一个节点,这一点这一题没有测试
        else if(value ==preOrder[i]||value == -preOrder[i] ){
            leftIndex = i;
        }
    }

    if(rightIndex == -1) {
        rightIndex = right;
    }
    if(leftIndex==-1){
        leftIndex = currentIndex + 1;
    }
    else{
        leftIndex++;
    }
    int leftHigh = leftIndex==rightIndex? currentColor: bulidTree(preOrder,leftIndex,rightIndex,currentColor) +currentColor;
    int rightHigh =  rightIndex == right? currentColor: bulidTree(preOrder,rightIndex,right,currentColor) + currentColor;

    if(leftHigh != rightHigh) {
        isRBTree = false;
    }
    int treeHigh = leftHigh > rightHigh ? leftHigh : rightHigh;

    return treeHigh ;

}
int main()
{
    int n,m,k;
    scanf("%d",&k);
    for(int i=0; i<k; i++) {
        scanf("%d",&n);
        int preOrder[n];
        for(int i=0; i<n; i++) {
            scanf("%d",&preOrder[i]);
        }
        isRBTree = true;

        bulidTree(preOrder,0,n,BLACK);
        if(preOrder[0]<0){
            isRBTree =false;
        }
        if(isRBTree) {
            printf("Yes\n");
        } else {
            printf("No\n");
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值