1135. Is It A Red-Black Tree (30)
2017-10-06 20:17
246 查看
题目详情:https://www.patest.cn/contests/pat-a-practise/1135
刚看到这道题的感觉很难,现在做出来了,感觉也就那么回事啊[傲娇脸]!
红黑树满足以下5条性质:
1、节点是红色或者黑色
2、根节点为黑色
3、每个叶节点(NIL节点,空节点)是黑色的
4、每个红色节点的子节点都是黑色的,即不能有两个连续的红色节点
5、从任一节点到其每个叶子的所有路径都包含相同数量的黑色节点
本题中,性质1、3是不用检查,需要检查的性质只有2、4、5。
首先明确,红黑树是一棵平衡二叉树,平衡二叉树是一棵二叉搜索树。那么红黑树满足平衡二叉树和二叉搜索树的性质。我是根据二叉搜索树的性质来还原这棵树的。
性质2只需要判断根节点的政府即可。
性质4用前序遍历检查
性质5用后续遍历来检查
刚看到这道题的感觉很难,现在做出来了,感觉也就那么回事啊[傲娇脸]!
红黑树满足以下5条性质:
1、节点是红色或者黑色
2、根节点为黑色
3、每个叶节点(NIL节点,空节点)是黑色的
4、每个红色节点的子节点都是黑色的,即不能有两个连续的红色节点
5、从任一节点到其每个叶子的所有路径都包含相同数量的黑色节点
本题中,性质1、3是不用检查,需要检查的性质只有2、4、5。
首先明确,红黑树是一棵平衡二叉树,平衡二叉树是一棵二叉搜索树。那么红黑树满足平衡二叉树和二叉搜索树的性质。我是根据二叉搜索树的性质来还原这棵树的。
性质2只需要判断根节点的政府即可。
性质4用前序遍历检查
性质5用后续遍历来检查
#include <iostream> #include <vector> #include <malloc.h> #include <math.h> #include <string.h> using namespace std; #define N 33 typedef struct BTree { struct BTree* leftBTree; int value; struct BTree* rightBTree; }BTree; BTree* buildBTree(int* pre,int start,int end)//start和end用来限制访问的范围 {//根据二叉搜索树的性质和红黑树前序遍历序列来还原红黑树 if (start==end)//起始位置和结束位置相同,那么代表空节点 return NULL; int i; for(i=start;i<end;i++)//找到比pre[start]的第一个位置后停止 {//根据二叉搜索树的性质,该位置右侧的数在右子树上 if( abs(pre[i])>abs(pre[start]) ) break; } BTree* root=(BTree*)malloc(sizeof(BTree));//建立"根节点" root->value=pre[start]; root->leftBTree=buildBTree(pre,start+1,i);//递归建立左子树 root->rightBTree=buildBTree(pre,i,end);//递归建立右子树 return root; } int postOrder(BTree* root)//后续遍历检查路径上是否由相同的黑色节点数量 { if(root!=NULL) { int leftBlack=postOrder(root->leftBTree);//leftBlack存左子树的黑色节点数量 int rightBlack=postOrder(root->rightBTree);//rightBlack存右子树的黑色节点数量 if ( leftBlack<0 || rightBlack<0 || rightBlack!=leftBlack ) return -1; //黑色节点数不相等,或左子树、右子树已经存在不等的黑色节点数则返回一个负数 else if(root->value<0)//本节点为红色,则不加上本节点 return leftBlack; else//本节点为黑色 return leftBlack+1;//加上本黑色节点 } return 0; } int previousOrder(BTree* root) //前序遍历用以检查是否有连续的两个红色节点 { if(root) { if(root->value<0)//本届点为红色节点 { if(root->leftBTree)//左子树非空 { if(root->leftBTree->value<0)//左节点为红色 return 1;//则返回真值(1),代表有连续的红色节点 } if(root->rightBTree)//右子树非空 { if(root->rightBTree->value<0)//右节点为红色 return 1;//则返回真值(1),代表有连续的红色节点 } } return previousOrder(root->leftBTree) || previousOrder(root->rightBTree);//递归进行检查 } return 0;//空节点则返回假值,代表没有连续的两个红色节点 } int main() { int k,n,preOrder ; scanf("%d",&k);//输入循环的次数 for(int i=0;i<k;i++) { scanf("%d",&n);//输入节点的个数,n为一个正数 memset(preOrder,0,n);//将preOrder数组的前n个元素全部置为0 for(int j=0;j<n;j++) scanf("%d",&preOrder[j]);//存储前序遍历的序列 if(preOrder[0]<0)//负号代表红色节点,根节点为红色,则不符合要求 {//保证根节点是黑色的 printf("No\n"); continue; } BTree* root=buildBTree(preOrder,0,n);//还原(构建)红黑树 //用后续遍历来判断是否连续的两个节点为红色,路径上的黑色节点数量是否相同 //balance用来存储路径的黑色节点是否相同,非负数相同,负数(-1)代表数量不相同 //continous用来存储两个红色的节点是否连续,1代表连续, int balance=postOrder(root); int continous=previousOrder(root); //如果路径上黑色节点数量不同或者存在连续的红色节点 if( balance<0 || continous==1) printf("No\n"); else printf("Yes\n"); } }
相关文章推荐
- 1135. Is It A Red-Black Tree (30)
- 1135. Is It A Red-Black Tree (30)
- PAT甲级 1135. Is It A Red-Black Tree (30) 建树+深搜
- PAT (Advanced Level)1135. Is It A Red-Black Tree (30) 指针 建树 深度优先遍历
- 1135. Is It A Red-Black Tree (30)[红黑树判断]
- pat1135 Is It A Red-Black Tree (30)(红黑树)
- PAT 1135. Is It A Red-Black Tree (30) 二叉搜索树建立 + 红黑树判断
- PAT甲级 1135.Is It A Red-Black Tree (30)
- 【PAT 1135. Is It A Red-Black Tree (30)】& 二叉树
- 1135. Is It A Red-Black Tree (30)-PAT甲级真题
- 1135. Is It A Red-Black Tree (30)(红黑树)
- PAT (Advanced Level) Practise 1135 Is It A Red-Black Tree (30)
- 1135. Is It A Red-Black Tree (30)
- 1135. Is It A Red-Black Tree (30) 红黑树
- 1135. Is It A Red-Black Tree (30)
- 1135. Is It A Red-Black Tree (30)/红黑树 搜索建树
- 1135. Is It A Red-Black Tree (30)(判断红黑树)
- 1135. Is It A Red-Black Tree (30)
- PAT甲级1135 Is It A Red-Black Tree
- (pat)A1135. Is It A Red-Black Tree