pat树问题总结3 建树

本文总结了PAT(A1115)和(A1135)两道题,这两道题均涉及到树的构建。A1115题要求根据给定数据构建二叉搜索树,并统计最后两层节点数量和。A1135题则需要判断给定的前序遍历序列是否构成一棵符合红黑树特性的树,实现方法是通过递归计算节点颜色和深度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

并不是说其他题不用建树,只是这类题是真正用一个build函数建。其实要看他们的输入,一般来说都会给出二叉树所有结点的data。

(A1115)输出一个二叉搜索树最后两层的结点个数a和b,以及他们的和c :“a + b = c”
点评:build一棵二叉树,dfs确认其深度及每层结点个数,最后按要求加和即可。

#include <iostream>
#include <vector>
using namespace std;
struct node {
    int v;
    struct node *left, *right;
};
node* build(node *root, int v) {
    if(root == NULL) {
        root = new node();
        root->v = v;
        root->left = root->right = NULL;
    } else if(v <= root->v)
        root->left = build(root->left, v);
    else
        root->right = build(root->right, v);
    return root;
}
vector<int> num(1000);
int maxdepth = -1;
void dfs(node *root, int depth) {
    if(root == NULL) {
        maxdepth = max(depth, maxdepth);
        return ;
    }
    num[depth]++;
    dfs(root->left, depth + 1);
    dfs(root->right, depth + 1);
    
}
int main() {
    int n, t;
    scanf("%d", &n);
    node *root = NULL;
    for(int i = 0; i < n; i++) {
        scanf("%d", &t);
        root = build(root, t);
    }
    dfs(root, 0);
    printf("%d + %d = %d", num[maxdepth-1], num[maxdepth-2], num[maxdepth-1] + num[maxdepth-2]);
    return 0;
}

(A1135)给一棵二叉搜索树的前序遍历,判断它是否为红黑树,是输出Yes,否则输出No。其中红黑树的特征:
1.根节点为黑色。
2.空的位置都算黑色。
3.如果一个结点是红色,那么他的所有孩子都是黑色。
4.从任意节点到叶子结点的路径中,黑色结点个数相同。
其中,输入时,负数表示黑色,正数表示红色。

分析:只要判断条件1,3,4即可。其中1,3很好判断。4任意节点默认为根节点,然后递归获得层数,要是根节点是红色就是层数加1,黑色就不用加。

#include<iostream>
#include<vector>
#include<cmath>
using namespace std;
vector<int> ans;
struct node{
	int data;
	node *lchild,*rchild;
};

node* create(node *root,int v){
	if(root==NULL){
		root=new node();
		root->data=v;
		root->lchild=root->rchild=NULL;
	}
	else if(abs(v)<abs(root->data)){
		root->lchild=create(root->lchild,v);
	}
	else{
		root->rchild=create(root->rchild,v);
	}
	return root;
}

bool judge1(node *root){ //判断若根是红,孩子是不是黑(空也算黑) 
	if(root==NULL) return true;
	if(root->data<0){
		if(root->lchild!=NULL&&root->lchild->data<0) return false;
		if(root->rchild!=NULL&&root->rchild->data<0) return false;
	}
	return judge1(root->lchild) && judge1(root->rchild);
}

int getnum(node *root){
	if(root==NULL) return true;
	int l=getnum(root->lchild);
	int r=getnum(root->rchild);
	return root->data>0 ? max(l,r)+1 : max(l,r);
}

bool judge2(node *root){ //从根节点到叶子结点每条路径黑色一样 
	if(root==NULL) return true;
	int l=getnum(root->lchild);
	int r=getnum(root->rchild);
	if(l!=r) return false;
	return judge2(root->lchild) && judge2(root->rchild);
}

int main(){
	int k,n;
	scanf("%d",&k);
	for(int i=0;i<k;i++){
		scanf("%d",&n);
		ans.resize(n); // 记得
		node *root=NULL; // 记得
		for(int j=0;j<n;j++){
			scanf("%d",&ans[j]);
			root=create(root,ans[j]);
		}
		if(ans[0]<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、付费专栏及课程。

余额充值