题意:
先说说红黑树的定义吧:
(1)每一个节点不是红色就是黑色
(2)根节点是黑色
(3)每个叶子节点都是黑色的(这里的叶子节点指的是NULL)
(4)如果一个节点是红色的,那么它的左右子节点都是黑色的
(5)从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
题目给出一个二叉搜索树的前序序列,需要我们判断这棵树是否是一棵红黑树
代码如下:
//红黑树
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<stack>
#include<map>
#define MAX 1020
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
int tag1,tag2,tag3,minlen=INF;
struct node{
int key;
node *parent,*left,*right;
};
node *root,*NIL;
void insert_node(int key){//插入节点
node *y=NIL;
node *x=root;
node *z=new node;
z->key=key;
z->left=NIL;
z->right=NIL;
while(x!=NIL){
y=x;
if(abs(z->key)<=abs(x->key)){
x=x->left;
}else{
x=x->right;
}
}
z->parent=y;
if(y==NIL){
root=z;
}else{
if(abs(z->key)<=abs(y->key)){
y->left=z;
}else{
y->right=z;
}
}
}
void dfs1(node *root){//判断条件(4)
//如果一个节点是红色的,那么它的左右子节点都是黑色的
if(root->key<0){
if(root->left!=NIL){
if(root->left->key<0){
tag1=1;
}
}
if(root->right!=NIL){
if(root->right->key<0){
tag1=1;
}
}
}
if(root->left!=NIL){
dfs1(root->left);
}
if(root->right!=NIL){
dfs1(root->right);
}
}
void dfs2(node *root,int cnt){
if(root==NIL){
if(tag3==0){
if(cnt<minlen){
minlen=cnt;
}
tag3=1;
}else{
if(cnt!=minlen) tag2=1;
}
return;
}
if(root->key>0){
dfs2(root->left,cnt+1);
}else{
dfs2(root->left,cnt);
}
if(root->key>0){
dfs2(root->right,cnt+1);
}else{
dfs2(root->right,cnt);
}
}
void dfs3(node *root){//判断条件(5)
//从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点
minlen=INF,tag3=0;
dfs2(root,0);//枚举每一个节点
if(root->left!=NIL){
dfs3(root->left);
}
if(root->right!=NIL){
dfs3(root->right);
}
}
int main(){
int k,n,key;
cin>>k;
for(int i=0;i<k;i++){
cin>>n;
root=NULL,NIL=NULL;
for(int j=0;j<n;j++){
cin>>key;
insert_node(key);
}
int flag=true;
tag1=0;
if(root->key<0){
flag=false;
}
if(flag){
dfs1(root);
if(tag1==1){
flag=false;
}
}
if(flag){
tag2=0;
dfs3(root);
if(tag2==1){
flag=false;
}
}
if(flag){
cout<<"Yes"<<endl;
}else{
cout<<"No"<<endl;
}
}
}
注意点:
(1)不可以通过先序序列和中序序列(先序序列排序后得到)进行建树,因为所给出的数据可能含有相同数据结点,此时,通过先序和中序序列是无法唯一确定一棵树的,而通过直接建立BST树的方式则可以唯一建树。
(2)红黑树(英语:Red–black tree)是一种自平衡二叉查找树。AVL树:在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。所以说红黑树不是一种AVL树,红黑树相对于AVL树来说,牺牲了部分平衡性以换取插入/删除操作时少量的旋转操作,整体来说性能要优于AVL树。
使用递归的建树方法来做:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<cmath>
#include<queue>
#include<cstring>
#include<vector>
#include<stack>
#include<map>
#define MAX 1020
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
struct node{
int val;
node *left,*right;
};
node* build_bst_tree(node* root,int v){
if(root==NULL){
root=(node *)malloc(sizeof(node));
root->val=v;
root->left=root->right=NULL;
return root;
}else if(abs(v)<=abs(root->val)){
root->left=build_bst_tree(root->left,v);
}else{
root->right=build_bst_tree(root->right,v);
}
return root;
}
bool judge1(node *root){//判断条件4
if(root==NULL) return true;
if(root->val<0) {
if(root->left!=NULL&&root->left->val<0) return false;
if(root->right!= NULL&&root->right->val< 0) return false;
}
return judge1(root->left)&&judge1(root->right);
}
int getNum(node *root) {
if(root==NULL) return 0;
int l=getNum(root->left);
int r=getNum(root->right);
return root->val>0?max(l,r)+1:max(l,r);
}
bool judge2(node *root) {//判断条件5
if(root==NULL) return true;
int l=getNum(root->left);
int r=getNum(root->right);
if(l!=r) return false;
return judge2(root->left)&&judge2(root->right);
}
int main(){
int k,n,tmp;
cin>>k;
for(int i=0;i<k;i++){
cin>>n;
node* root=NULL;
for(int j=0;j<n;j++){
cin>>tmp;
root=build_bst_tree(root,tmp);
}
if(root->val<0||judge1(root)==false||judge2(root)==false)
printf("No\n");
else
printf("Yes\n");
}
return 0;
}