PTA判断是否是同一棵二叉搜索树
思路:将第一个序列作为初始序列建树,然后把之后的序列的元素按顺序在树中做查找,通过比较每次查找过程中所遇到的节点是否在序列中出现过,来判定该序列和初始序列是否是同一棵二叉搜索树
#include<stdio.h>
#include<stdlib.h>
typedef struct TreeNode *Tree;
struct TreeNode
{
int v;
Tree Left,Right;
int flag;
};
Tree MakeTree(int N);
Tree NewNode(int V);
Tree Insert(Tree T,int V);
int check(Tree T,int V);
int Judge(Tree T,int N);
void ResetT(Tree T);
void FreeTree(Tree T);
int main()
{
int N,L,i;
Tree T;
scanf("%d",&N);
while(N)
{
scanf("%d",&L);
T=MakeTree(N);
for(i=0;i<L;i++)
{
if(Judge(T,N))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
ResetT(T);//清除T中的标记flag
}
FreeTree(T);
scanf("%d",&N);
}
return 0;
}
Tree MakeTree(int N)
{
Tree T;
int i,V;
scanf("%d",&V);
T=NewNode(V);//用读入的第一个数据作为根节点建一棵树
for(i=1;i<N;i++)//通过for循环把之后读到的节点插到树中
{
scanf("%d",&V);
T=Insert(T,V);
}
return T;
}
Tree NewNode(int V)//建立一个只有根节点的新树
{
Tree T=(Tree)malloc(sizeof(struct TreeNode));
T->v=V;
T->Left=T->Right=NULL;
T->flag=0;
return T;
}
Tree Insert(Tree T,int V)//把新节点插入树中
{
if(!T)//如果是空树,以新节点为根节点建立一棵新树
{
T=NewNode(V);
}
else//如果树不空,将新节点与根节点作比较,然后递归调用Insert函数把新节点插入
{
if(V>T->v)
{
T->Right=Insert(T->Right,V);
}
else
{
T->Left=Insert(T->Left,V);
}
}
return T;
}
int check(Tree T,int V)//在树T中查找V,将V在T中的查找路径与V所在的序列相比,如果路径中出现没遇到过的节点,则可以判定不一致
{
if(T->flag)//如果当前节点被访问过,递归调用check函数往下查找
{
if(V<T->v)//小于当前节点,查找左子树
{
return check(T->Left,V);
}
else if(V>T->v)//大于,查找右子树
{
return check(T->Right,V);
}
else//如果相等,说明在该序列中有一个整数出现了第二次,则可以判定不一致
{
return 0;
}
}
else//当前节点没有被访问过
{
if(V==T->v)//如果刚好相等,说明该节点就是要找的节点,标记该节点flag为1
{
T->flag=1;
return 1;
}
else//当前节点没被访问过,又不是要找的节点,说明碰到了一个没见过的节点,判定不一致
{
return 0;
}
}
}
int Judge(Tree T,int N)
{
int i,V,flag=0;//flag:0代表目前还一致,1代表已经不一致 ,用flag标记的目的是让程序在发现不一致的时候,不退出循环,而是继续把剩余的数据读完
scanf("%d",&V);
if(V!=T->v)
{
flag=1;//如果根节点不同,出现不一致,flag设为1
}
else
{
T->flag=1;//如果相同,把该根节点的标记设为1,表示已经访问过
}
for(i=1;i<N;i++)
{
scanf("%d",&V);
if((!flag)&&(!check(T,V)))//如果之前出现过不一致,即flag值本来就是1,不用check直接跳过本语句继续读入数据;如果flag是0,而check比较结果是不一致,把flag设为1
{
flag=1;
}
}
if(flag)//不一致,返回0
{
return 0;
}
else//一致,返回1
{
return 1;
}
}
void ResetT(Tree T)//清除T中各节点的flag标记
{
if(T->Left)
{
ResetT(T->Left);
}
if(T->Right)
{
ResetT(T->Right);
}
T->flag=0;
}
void FreeTree(Tree T)//释放T的空间
{
if(T->Left)
{
FreeTree(T->Left);
}
if(T->Right)
{
FreeTree(T->Right);
}
free(T);
}