目的:判断是否是红黑树
输入:
K <= 30 例子数量
N <= 30 节点数量
先序序列
负数代表是红点。
输出:
是红黑树:输出YES
不是:输出NO
算法:
红黑树特点:
1.每一个节点要不红要不白
2.根节点是黑色
3.每一个叶子(NULL)是黑色的
这句话的意思是,如果这个节点为NULL,则为黑色。
4.如果一个节点是红色,它的两个孩子都是黑色
5.对于每一个节点,从节点到它的子孙的叶子节点,每条简单路径上黑点数目一样多。
判断是否为红黑树:
1.根节点是否为黑色
2.红色节点的孩子是否为黑色。若孩子存在
3.每个节点到它的子树叶子节点,路径上的黑点数目是否一样多。
红黑树是一颗二叉查找树
建树的过程中,判断。
知道先序序列,构造二叉查找树,你不熟练呀。。。
#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
struct node{
int data;
node* left,* right;
}*root;
int K,N;
vector<int> pre;
vector<node*> path;
int cnt;
bool flag = true;
node* newnode(int x)
{
node* now = new node;
now->data = x;
now->left = NULL;
now->right= NULL;
return now;
}
void creat(node* &root,int left,int right)
{
if(left>right) return;
root = newnode(pre[left]);
int u = left+1;
for(int i=left;i<=right;i++)
{
if(abs(pre[i])>abs(pre[left]))
{
u = i;
break;
}
}
creat(root->left,left+1,u-1);
creat(root->right,u,right);
}
void visit(node* root)
{
if(flag==false) return;
if(root==NULL)
{
int num = 0;
for(int i=0;i<path.size();i++)
{
if(path[i]->data>0)
{
num++;
}
}
if(cnt!=0&&cnt!=num)
{
flag = false;
}
cnt = num;
return;
}
path.push_back(root);
if(root->data<0)
{
if(root->left!=NULL&&root->left->data<0)
{
flag = false;
}
if(root->right!=NULL&&root->right->data<0)
{
flag = false;
}
}
visit(root->left);
visit(root->right);
path.pop_back();
}
int main()
{
scanf("%d",&K);
for(int i=0;i<K;i++)
{
scanf("%d",&N);
pre.resize(N);
for(int j=0;j<N;j++)
{
scanf("%d",&pre[j]);
}
creat(root,0,N-1);
cnt = 0;
flag = true;
path.clear();
visit(root);
if(root->data>0&&flag==true)
{
printf("Yes\n");
}else
{
printf("No\n");
}
}
return 0;
}
反思:红黑树不了解。题目看不太懂。逻辑混乱。通过先序序列对二叉查找树建树不熟练。多写子函数。模块化程度很高。不容易出错。而且多用递归,代码简洁。