小白专场—是否同一棵二叉搜索树

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。

输入格式:

输入包含若干组测试数据。每组数据的第1行给出两个正整数N (≤10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。最后L行,每行给出N个插入的元素,属于L个需要检查的序列。

简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。

输出格式:

对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。

在这里插入图片描述
求解思路
两个序列是否对应相同搜索树的判别

  • 1、分别建两棵搜索树的判别方法
    • 项目根据两个序列分别建树,再判别树是否一样* 根据两个序列分别建树,再判别树是否一样
  • 2、不建树的判别方法
    在这里插入图片描述
  • 3、建立一棵树,再判别其他序列是否与该树一致

首先是根据第一种思路:

1.建立两棵树对比其元素

#include<iostream>
#include<stdlib.h>
using namespace std;

#define elemtype int

typedef struct BiNode
{
	int data;
	struct BiNode *left;
	struct BiNode *right;
}BiNode,*BiTree;

void Insert(BiTree &tree,BiTree &btp)
{
	if (tree == NULL)
		return;
	if (btp->data > tree->data)
	{
		if (tree->right == NULL)
			tree->right = btp;
		else
			Insert(tree->right, btp);
	}
	if (btp->data < tree->data)
	{
		if (tree->left == NULL)
			tree->left = btp;
		else
			Insert(tree->left,btp);
	}
}

void SearchTree(BiTree& tree,BiTree &btp)
{
	if (tree == NULL)
		tree = btp;
	else
		Insert(tree,btp);
}

void CreateOrderBinaryTree(BiTree &tree, int n)
{
	for (int i = 0; i < n; i++)
	{
		int idata;
		cin >> idata;				//读入树中的每一个结点数据
		BiTree btp;
		btp = (BiTree)malloc(sizeof(BiNode));
		btp->data = idata;
		btp->left = NULL;
		btp->right = NULL;
		SearchTree(tree,btp);
	}
}

//判断两棵树是否相同
bool Judge(BiTree tree,BiTree tmptree)
{
	if (tree == NULL && tmptree == NULL)
		return true;
	else if ((tree != NULL&&tmptree == NULL) || (tree == NULL&&tmptree != NULL))
		return false;
	else if ((tree!=NULL&&tmptree!=NULL) && (tree->data != tmptree->data))
		return false;
	return Judge(tree->left,tmptree->left) && Judge(tree->right,tmptree->right);
}

//释放空间
void freedom(BiTree &pRoot)
{
	if (pRoot->left == NULL&&pRoot->right)
		free(pRoot);
	else if (pRoot->left != NULL)
		freedom(pRoot->left);
	else if (pRoot->right != NULL)
		freedom(pRoot->right);
}

int main()
{
	int N, L;//n表示每一棵有几个结点,l表示有几颗树要与该树比较
	cin >> N;
	while (N)
	{
		cin >> L;
		BiTree tree=NULL;
		CreateOrderBinaryTree(tree,N);

		for (int i = 0; i < L; i++)
		{
			BiTree tmptree = NULL;
			CreateOrderBinaryTree(tmptree, N);
			bool issame=Judge(tree,tmptree);
			if (issame == true)
				cout << "Yes" << endl;
			else
				cout << "No" << endl;
			freedom(tmptree);		//不要忘记释放空间
		}
		freedom(tree);
		cin >> N;				//读入下一个数据,如果输入0,程序结束
	}

}

在这里插入图片描述

之后根据第三种思路

2.建立一棵树,再判别其他序列是否与该树一致

先讲程序框架搭建

int main() 
{ 对每组数据
	读入N和L
	根据第一行序列建树T
	依据树T分别判别后面的L个序列是否能与T形成同一搜索树并输出结果
	return 0;
}

需要设计的主要函数:

  • 读数据建搜索树T
  • 判别一序列是否与T构成一样的搜索树

如何判别
在这里插入图片描述
如何判别序列3 2 4 1是否 与树T一致?
方法:在树T中按顺序搜索序列3 2 4 1中的每个数

  • 如果每次搜索所经过的结点在前面均出现过,则一致
  • 否则(某次搜索中遇到前面未出现的结点),则不一致
#include<iostream>
#include<stdlib.h>
using namespace std;

#define Elemtype int

typedef struct BiNode
{
	Elemtype data;
	int flag;			//0:还没被访问过,1:已经访问过了
	struct BiNode *left;
	struct BiNode *right;
}BiNode,*BiTree;

void Searchtree(BiTree &tree, BiTree &btp)
{
	if (tree == NULL)
		return;
	if (btp->data > tree->data)
	{
		if (tree->right == NULL)
			tree->right = btp;
		else
			Searchtree(tree->right, btp);
	}
	else if (btp->data < tree->data)
	{
		if (tree->left == NULL)
			tree->left = btp;
		else
			Searchtree(tree->left, btp);
	}
}

void Insert(BiTree &tree,BiTree &btp)
{
	if (tree == NULL)
		tree = btp;
	else
		Searchtree(tree,btp);
}

void CreateOrderBinaryTree(BiTree &tree, int n)
{
	for (int i = 0; i < n; i++)
	{
		int da;
		cin >> da;
		BiTree btp = (BiTree)malloc(sizeof(BiNode));
		btp->data = da;
		btp->left = btp->right = NULL;
		btp->flag=0;
		Insert(tree,btp);
	}
}

bool check(BiTree tree, int da)
{
	if (tree->flag == 0)
	{
		if (tree->data == da)
		{
			tree->flag = 1;		//将访问过的结点标志设为1
			return true;
		}
		else
			return false;
	}
	else
	{
		if (da > tree->data)
			check(tree->right, da);
		else if (da < tree->data)
			check(tree->left, da);
		else
			return false;
	}
}

bool Judge(BiTree tree,int n)
{
	int da,mark = 0;			//mark:0代表目前还一致,1代表已经不一致
	cin >> da;
	if (tree->data != da)
		mark = 1;
	else
		tree->flag = 1;			//将访问过的结点标志设为1

	//每次循环判断访问该数据的路径上有没有没访问过的数据,有,两树不一致
	for (int i = 1; i < n; i++)
	{
		cin >> da;
		//当发现序列中的某个数与T不一致时,必须把序列后面的数都读完!
		if ((mark == 0) && (check(tree, da)==false))
			mark = 1;
	}
	if (mark == 0)
		return true;
	else
		return false;
}

int main()
{
	int N, L;
	cin >> N;
	while (N)
	{
		cin >> L;
		BiTree tree=NULL;
		CreateOrderBinaryTree(tree, N);
		for (int i = 0; i < L; i++)		//每次循环判断一棵树
		{
			bool issame = Judge(tree, N);
			if (issame==true)
				cout << "Yes" << endl;
			else
				cout << "No" << endl;
		}
		cin >> N;						//读入下一组数据,为0结束函数
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/happyjacob/article/details/83240502