1135 Is It A Red-Black Tree

There is a kind of balanced binary search tree named red-black tree in the data structure. It has the following 5 properties:

(1) Every node is either red or black.
(2) The root is black.
(3) Every leaf (NULL) is black.
(4) If a node is red, then both its children are black.
(5) For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.
For example, the tree in Figure 1 is a red-black tree, while the ones in Figure 2 and 3 are not.
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Input Specification:

Each input file contains several test cases. The first line gives a positive integer K (≤30) which is the total number of cases. For each case, the first line gives a positive integer N (≤30), the total number of nodes in the binary tree. The second line gives the preorder traversal sequence of the tree. While all the keys in a tree are positive integers, we use negative signs to represent red nodes. All the numbers in a line are separated by a space. The sample input cases correspond to the trees shown in Figure 1, 2 and 3.

Output Specification:

For each test case, print in a line “Yes” if the given tree is a red-black tree, or “No” if not.

Sample Input:

3
9
7 -2 1 5 -4 -11 8 14 -15
9
11 -2 1 -7 5 -4 8 14 -15
8
10 -7 5 -6 8 15 -11 17

Sample Output:

Yes
No
No

思路

注意在建图的时候就有可能不是树

cpp代码

#include<iostream>
#include<unordered_map>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
const int N=50;
unordered_map<int,int> pos,l,r,judge;//负红,正黑
int pre[N],post[N];
bool st=true,st1=false;
vector<int> vec;
int path[N];
int build(int inl,int inr,int prel,int prer){
    int root=pre[prel];
    int k=pos[root];
    if(inl>k||k>inr){
        st1=false;
        return root;
    }
    if(inl<k)l[root]=build(inl,k-1,prel+1,k-1-inl+prel+1);
    if(k<inr)r[root]=build(k+1,inr,k-1-inl+prel+1+1,prer);
    
    return root;
}
void dfs(int u,int deep){
	if(judge[u]==-1){//如果该节点是红的 
		if(l.count(u)){
			if(judge[l[u]]==-1)st=false;
		}
		if(r.count(u)){
			if(judge[r[u]]==-1)st=false;
		}
	}
	
	path[deep]=judge[u];
	
	if(!l.count(u)||!r.count(u)){//注意这里是||而不是&&,因为leaf是空的,因此当没有左孩子或者右孩子时就需要判断
		int num=0;
		for(int i=0;i<=deep;i++)
			if(path[i]==1)num++;
		vec.push_back(num);
	}
	
	if(l.count(u))dfs(l[u],deep+1);
	
	if(r.count(u))dfs(r[u],deep+1);
}
int main(){
    int q;
    cin>>q;
    while(q--){
    	st=true;
    	st1=true;
    	vec.clear();
    	pos.clear();
    	l.clear();
    	r.clear();
        int n;
        cin>>n;
        for(int i=0;i<n;i++){
            int x;cin>>x;
            if(x<0)x=abs(x),judge[x]=-1;
            else judge[x]=1;
            pre[i]=x;
            post[i]=x;
        }
        
        sort(post,post+n);
        
        for(int i=0;i<n;i++)pos[post[i]]=i;
       
        int root=build(0,n-1,0,n-1);
        if(!st1){
             puts("No");
            continue;
        }
        if(judge[root]==-1){
            puts("No");
            continue;
        }
        
        dfs(root,0);
        if(!st){
        	puts("No");
        	continue;
		}
		int t=vec[0];
		bool flag=true;
		for(int i=1;i<vec.size();i++){
			if(vec[i]!=t)flag=false;
		}
		if(!flag){
			puts("No");
			continue;
		}
		puts("Yes");
    }
}
### 左倾红黑树 (Left-Leaning Red-Black Tree, LLRB) 的实现与解释 左倾红黑树是一种特殊的红黑树变体,由 Robert Sedgewick 提出并优化。它通过强制所有的红色链接都向左倾斜来简化标准红黑树的操作逻辑[^1]。 #### 基本性质 LLRB 继承了传统红黑树的核心特性,同时引入了一些额外约束条件: - **节点颜色**:每个节点要么是黑色,要么是红色。 - **根节点始终为黑色**。 - **任何路径上连续两个红色节点不可共存**(即不存在“双红”情况)。 - 所有叶子节点到根的距离相同。 - 只允许左侧存在红色连接线;右侧不允许出现红色边。 这些规则使得平衡操作更加直观易懂,并减少了旋转次数。 #### 关键函数说明 以下是几个重要的辅助方法用于维护上述不变量: ##### `isRed` 方法 判断给定节点及其子节点的颜色状态。 ```java private boolean isRed(Node node){ if(node == null)return false; return node.color == RED; } ``` ##### 插入新元素后的调整过程 当执行插入动作时可能会破坏原有的结构均衡性,则需调用三个基本变换——翻转颜色(`flipColors`)、右旋(`rotateRight`)以及左旋(`rotateLeft`)来进行修正。 ###### flipColors 函数 改变当前节点与其子女之间的相对关系。 ```java private void flipColors(Node h){ h.color = !h.color; h.left.color = !h.left.color; h.right.color = !h.right.color; } ``` ###### rotateRight 和 rotateLeft 函数 分别对应顺时针方向和逆时针方向上的结构调整。 ```java // Right Rotation Example Code Here... private Node rotateRight(Node h){ ... } // Left Rotation Example Code Here... private Node rotateLeft(Node h){ ... } ``` 完成以上基础组件定义之后,在实际 put() 或者 insert() 过程里就可以利用它们自动保持整个数据集合处于良好形态之中。 最终得到的结果是一个高度接近 log₂N 的自适应查找表,支持高效的动态集合作业处理需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值