PAT甲级 1135 Is It A Red-Black Tree 红黑树

39 篇文章 0 订阅
3 篇文章 0 订阅

在这里插入图片描述
在这里插入图片描述

题意:

先说说红黑树的定义吧:
(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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值