PTA 7-4 是否为同一颗二叉树(三种解法)
程序员文章站
2022-06-07 23:41:47
...
PTA 7-4 是否为同一颗二叉树(三种解法)
清晰思路参照: mooc → 浙大《数据结构》课程 → 第四讲 树(中)小白专场
题目详细:
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。
输入格式:
输入包含若干组测试数据。每组数据的第1行给出两个正整数N (≤10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。最后L行,每行给出N个插入的元素,属于L个需要检查的序列。
简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。
输出格式:
对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。
输入样例:
4 2 3 1 4 2 3 4 1 2 3 2 4 1 2 1 2 1 1 2 0
输出样例:
Yes No No
代码部分
1.分别建两颗搜索树的判别方法
根据两个序列分别建树,再判别树是否一样
#include<stdio.h>
#include<stdlib.h>
#define Max 10
typedef struct BNode *BST;
struct BNode{
int num;
BST Left;
BST Right;
};
BST Insert(BST T,int a)
{
if(!T)//空结点时即为要插入的地方,建立新结点
{
BST Node = (BST)malloc(sizeof(BST));
Node->num = a;
Node->Left = Node->Right = NULL;
return Node;
}
else{
if(T->num>a) T->Left=Insert(T->Left,a); //小于根节点,左插
else T->Right = Insert(T->Right,a);//大于根节点,右插
}
return T;
}
BST BuildTree(int N)
{
BST T = (BST)malloc(sizeof(BST));
scanf("%d",&T->num);//建立根结点
T->Left=T->Right=NULL;
for(int i =1;i<N;i++){
int a;
scanf("%d",&a);
T = Insert(T,a);//建立二叉搜索树
}
return T;
}
int isSameBST(BST T,BST test)
{
int flag = 1;
if(T&&test){
if(T->num != test->num) return 0;//两个结点的值不同,返回0
flag = isSameBST(T->Left,test->Left);//递归判断左子树
if(!flag) return 0;
flag = isSameBST(T->Right,test->Right);//递归判断右子树
if(!flag) return 0;
}
return flag;
}
int main()
{
while(1){
int N;
scanf("%d",&N);
if(N==0) break; //输入0,程序终止
int n_test;
scanf("%d",&n_test);
BST T = BuildTree(N); //建立二叉搜索树
for(int i=0;i<n_test;i++){
BST test = BuildTree(N); //建立要测试的二叉搜索树
int flag = isSameBST(T,test); //判断是否为同一颗BST树
if(flag) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
结果展示:
2.不建树的判别方法
#include<stdio.h>
#include<stdlib.h>
#define MAX 10
int Judge(int List[],int Test[],int N)
{
if(List[0]!=Test[0])return 0;
int flag = 1;
int root = List[0];
int List_L[MAX],List_R[MAX],Test_L[MAX],Test_R[MAX];
int L1=0,L2=0,R1=0,R2=0;
for(int i=1;i<N;i++) //按照大于或小于根节点,分为左右子树
{
if(List[i]<root) List_L[L1++]=List[i];
if(List[i]>root) List_R[R1++] = List[i];
if(Test[i]<root) Test_L[L2++]=Test[i];
if(Test[i]>root) Test_R[R2++]=Test[i];
}
if(L1>0&&L2>0&&L1==L2) if(!Judge(List_L,Test_L,L1)) return 0;
if(R1>0&&R2>0&&R1==R2) if(!Judge(List_R,Test_R,R1)) return 0;
return 1;
}
int main()
{
while(1)
{
int N,n_test;
scanf("%d",&N);
if(!N) break;
scanf("%d",&n_test);
int List[MAX],Test[MAX];
for(int i=0;i<N;i++) scanf("%d",&List[i]);
for(int i=0;i<n_test;i++){
int flag = 0;
for(int j=0;j<N;j++) scanf("%d",&Test[j]);
flag = Judge(List,Test,N);
if(flag) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
自己觉得应该有更精简的写法,但是目前实力不太可,有些许的繁琐难懂/(ㄒoㄒ)/~~
结果展示:
3.建一棵树,再判别其他序列是否与该树一致
#include<stdio.h> #include<stdlib.h> #define MAX 10 typedef struct TNode* Tree; struct TNode{ int num; Tree Left; Tree Right; int check; //标记符 }; Tree NewNode(int a) { Tree T = (Tree)malloc(sizeof(struct TNode)); T->num = a; T->Left =T->Right = NULL; T->check = 0; return T; } Tree Insert(Tree T,int a) { if(!T) T = NewNode(a); else{ if(T->num>a) T->Left = Insert(T->Left,a); else T->Right = Insert(T->Right,a); } return T; } Tree BuildTree(int N)//建树过程基本一致 { Tree T ; int a; scanf("%d",&a); T = NewNode(a); for(int i=1;i<N;i++){ scanf("%d",&a); T = Insert(T,a); } return T; } int check(Tree T,int a) { if(T->check) //该结点已经判断过 { if(T->num a) return check(T->Left,a); //大于判断值,找左子树 else if(T->num < a) return check(T->Right,a); //小于判断值,找右子树 else return 0; } else//该结点没有遍历过 { if(T->num == a)//等于判断值,树的标记符记为1 { T->check =1; return 1; } else return 0;//否则,返回0 } } int isSame(Tree T,int N) { int flag = 0;//设置flag,要保证所有数字都输入进去,防止干扰下一个测试树的判断 int a = 0; scanf("%d",&a); if(T->num != a) flag =1; else T->check = 1; for(int i=1;i<N;i++){ scanf("%d",&a); if((!flag) && (!check(T,a)) ) flag =1; } return flag?0:1; } void Reset(Tree T) // 判断完一组测试数列后,对照树标记符记为0 { if(T->Left) Reset(T->Left); if(T->Right) Reset(T->Right); T->check = 0; } void FreeTree(Tree T) // 释放树 { if(T->Left) FreeTree(T->Left); if(T->Right) FreeTree(T->Right); free(T); } int main() { while(1) { int N, n_test; scanf("%d",&N); if(!N) break; scanf("%d",&n_test); Tree T = BuildTree(N); for(int i=0;i<n_test;i++){ int flag =0; flag = isSame(T,N); if(flag) printf("Yes\n"); else printf("No\n"); Reset(T); } FreeTree(T); } return 0; }
基本是照着老师的代码敲下来的
结果展示:
上一篇: SAE空间域名绑定和域名跳转的方法详解
下一篇: 51Nod-1476-括号序列的最小代价