是否同一颗二叉树

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

输入格式:

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

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

输出格式:
在这里插入图片描述
对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。

求解思路
两个序列是否对应相同搜索树的判别

1、分别建两棵搜索树的判别方法
项目根据两个序列分别建树,再判别树是否一样* 根据两个序列分别建树,再判别树是否一样
2、不建树的判别方法
在这里插入图片描述
3、建立一棵树,再判别其他序列是否与该树一致
第一种方法:先建立一个二叉树,在此树中查找后面序列的节点,若每次查找所经过的节点在之前都出现过则一致,若某次查找经过的节点没有出现过则不一致。

#include <iostream>
using namespace std;
typedef struct TreeNode *Tree;
struct TreeNode
{
	TreeNode(){}
	~TreeNode(){}
	int content;
	Tree left, right;
	int flag;
};
Tree MakeTree(int N);
Tree NewNode(int contents);
Tree Insert(Tree T, int contents);
int Judge(Tree T, int N);
void ResetT(Tree T);
int check(Tree T, int V);
void FreeTree(Tree T);


Tree MakeTree(int N)//建树
{
	Tree T=nullptr;
	int i, contents;
	cin >> contents;
	T = NewNode(contents);
	for (i = 1; i < N;++i)//插入树节点
	{
		cin >> contents;
		T = Insert(T, contents);
	}
	return T;
}

Tree NewNode(int contents)
{
	Tree T = (Tree)malloc(sizeof(struct TreeNode));
	T->content = contents;
	T->left = T->right = nullptr; 
	T->flag = 0;
	return T;
}

Tree Insert(Tree T, int contents)//插入树节点
{
	if (!T)
		T = NewNode(contents);//若是空树,创建新的节点
	else{
		if (contents<T->content)       //若要插入的节点值小于当前节点值,插入左子树
			T->left = Insert(T->left,contents);
		else T->right = Insert(T->right,contents);
	}
	return T;
}

int Judge(Tree T, int N)//判断是否为同一二叉树
{
	int i, V, flag = 0;//flag为0说明还是一致的
	cin >> V;
	if (V != T->content)flag = 1;//根节点不相同说明不是同一颗
	else T->flag = 1;             //相同则把当前节点的flag变成1,表示已经路过了
	for (i = 1; i < N;++i)
	{
		cin >> V;//输入剩余的节点值
		if ((!flag)&&(!check(T, V)))flag =1;//若flag=0(这一步之前还是一致的),那么进行这次check,if=0(这次不一致)
	}
	if (flag)return 0;
	else return 1;
}

void ResetT(Tree T)
{
	if (T->left)ResetT(T->left);
	if (T->right)ResetT(T->right);
	T->flag = 0;
}

int check(Tree T, int V)
{
	if (T->flag)//如T已被路过
	{
		if (V < T->content)return check(T->left, V);
		else if (V>T->content)return check(T->right, V);
		else return 0;
	}
	else//没被路过
	{
		if (V==T->content)//该节点就是我们要找的
		{
			T->flag = 1;
			return 1;
		}
		else return 0;
	}
}


void FreeTree(Tree T)
{
	if (T->left)FreeTree(T->left);
	if (T->right)FreeTree(T->right);
	free(T);
}

int main()
{
	int N, L, i;
	Tree T;
	cin >> N;
	while (N)
	{
		cin >> L;
		T = MakeTree(N);
		for (i = 0; i < L; ++i)
		{
			if (Judge(T, N))cout << "Yes"<<endl; 
			else cout << "No"<<endl;
		//	ResetT(T);
		}
	//	FreeTree(T);
		cin >> N;
	}
	system("pause");
	return 0;
}

第二种方法:每个序列建立一棵树,比较他们的先序遍历序列,一致则是,否则不是

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

using namespace std;
int N, L, pos, samejudgement[100];


typedef struct node
{
	node(int a, node* b, node* c)
	{
		data = a;
		l = b;
		r = c;
	}
	int data;
	struct node *l;
	struct node *r;
}*BST;

void PreOrderTraverse(BST T)
{
	if (T)
	{
		samejudgement[pos++] = T->data;
		PreOrderTraverse(T->l);
		PreOrderTraverse(T->r);
	}
}

bool PreOrderTraverse_test(BST T)
{
	if (T)
	{

		// cout<<"gg1111     "<<samejudgement[pos]<<"     "<<pos<<endl;
		if (samejudgement[pos++] != T->data) return false;
		// cout<<"gg2222   "<<pos<<endl;
		if (!PreOrderTraverse_test(T->l)) return false;
		if (!PreOrderTraverse_test(T->r)) return false;
	}

	return true;

}

void Inset_BST(BST &T, int data)
{
	if (T == NULL)
	{
		T = new node(data, NULL, NULL);
	}
	else if (T->data > data)
	{
		Inset_BST(T->l, data);
	}
	else Inset_BST(T->r, data);
}



int main()
{

	while (scanf("%d", &N) != EOF)
	{
		if (N) scanf("%d", &L);
		else break;

		pos = 0;
		memset(samejudgement, 0, sizeof(samejudgement));
		BST tree = NULL;
		for (int i = 0; i < N; i++)
		{
			int t; scanf("%d", &t);
			Inset_BST(tree, t);
		}

		PreOrderTraverse(tree);
		//for(int i=0;i<pos;i++) cout<<"输出中间值   "<<samejudgement[i]<<endl;

		bool flag = true;
		for (int i = 0; i < L; i++)
		{
			flag = true;
			BST test_tree = NULL;
			pos = 0;
			for (int j = 0; j < N; j++)
			{
				int t; scanf("%d", &t);
				Inset_BST(test_tree, t);
			}
			//PreOrderTraverse_test(test_tree);
			if (!PreOrderTraverse_test(test_tree)) flag = false;
			if (flag) printf("Yes\n");
			else printf("No\n");
		}

		//if(flag) printf("Yes\n");
		//else printf("No\n");

	}

	return 0;

}

第三种不建树的方法:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于给定的两个序列,我们可以通过构建二叉搜索树来判断它们是否可以组成同一颗二叉搜索树。 首先,我们需要明确二叉搜索树的定义:对于任意节点,其左子树的所有节点值都小于它,右子树的所有节点值都大于它。 我们可以按照以下步骤来构建二叉搜索树: 1. 创建一个空的二叉搜索树。 2. 遍历第一个序列中的所有元素,依次将它们插入到二叉搜索树中。 3. 遍历第二个序列中的所有元素,依次在二叉搜索树中查找是否存在该元素。如果找到了该元素,则继续遍历下一个元素;如果没有找到该元素,则说明两个序列无法组成同一棵二叉搜索树。 如果两个序列可以组成同一棵二叉搜索树,那么我们可以进一步判断它是否是平衡二叉树。 平衡二叉树是指对于任意节点,其左子树和右子树的高度差不超过1。我们可以使用递归的方式来判断一棵二叉树是否是平衡二叉树: 1. 如果当前节点为空,则返回 True。 2. 计算当前节点的左子树高度和右子树高度的差值。如果差值大于1,则返回 False。 3. 分别递归判断当前节点的左子树和右子树是否是平衡二叉树。如果左子树和右子树都是平衡二叉树,则返回 True;否则,返回 False。 综上所述,我们可以通过构建二叉搜索树并判断其是否是平衡二叉树来判断给定的两个序列是否可以组成同一颗平衡二叉树
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值