欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;
}

结果展示:
PTA 7-4 是否为同一颗二叉树(三种解法)

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ㄒ)/~~

结果展示:
PTA 7-4 是否为同一颗二叉树(三种解法)

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;	
} 

基本是照着老师的代码敲下来的

结果展示:
PTA 7-4 是否为同一颗二叉树(三种解法)

相关标签: 算法 数据结构