MOOC数据结构课程 题集09 是否同一棵二叉搜索树

04-树4 是否同一棵二叉搜索树 (25 分)

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{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

 先建立搜索树,然后对要检查序列 squ 里的每一个数进行查找(设目前找的是第 i 个数),并且记录下查找的路径 through。

若 through 中所有的数都能在 squ[i] 之前的数中被找到,那么就继续检查

当 squ 中所有数都被查完且满足上面的条件就是同一棵搜索树

#include <iostream>
#define Tree int
#define MAX_SIZE 10

typedef struct _tree_node
{
	Tree data;
	Tree Left;
	Tree Right;
} Tree_node;

void build_tree(int N, Tree_node BTree[], Tree root);
bool is_sam_tree(Tree_node [], Tree [], int N, Tree root);
bool check_squ(Tree[], Tree[], int , int );

int main()
{
	int N, L,is_first_time = 1;
	Tree root = 0;
	std::cin >> N >> L;
	while (N != 0)
	{
		Tree_node BTree[MAX_SIZE];
		std::cin >> BTree[root].data;
		BTree[root].Left = BTree[root].Right = -1;
		build_tree(N, BTree, root);
		//读入序列,判断是否为同一搜索树,然后输出
		bool flag;
		for (int i = 0; i < L; i++)
		{
			Tree squ[MAX_SIZE];
			for (int i = 0; i < N; i++)
				std::cin >> squ[i];
			flag = is_sam_tree(BTree, squ, N, root);//判断
			//按格式输出
			if (is_first_time) 
				is_first_time = 0;
			else 
				std::cout << std::endl;
			if (flag)
				std::cout << "Yes";
			else
				std::cout << "No";
			//===========
		}
		//==========================
		std::cin >> N;
		if (N != 0) std::cin >> L;
	}

	return 0;
}

void build_tree(int N, Tree_node BTree[], Tree root)
{
	Tree pos;
	for (int i = 1; i < N; i++)
	{
		pos = root;
		std::cin >> BTree[i].data;
		BTree[i].Left = BTree[i].Right = -1;
		while (1)
		{
			if (BTree[pos].data < BTree[i].data)
			{
				if (BTree[pos].Right != -1)
					pos = BTree[pos].Right;
				else 
				{
					BTree[pos].Right = i;
					break;
				}
			}
			else
			{
				if (BTree[pos].Left != -1)
					pos = BTree[pos].Left;
				else
				{
					BTree[pos].Left = i;
					break;
				}
			}
		}
	}
}

bool is_sam_tree(Tree_node BTree[], Tree squ[], int N, Tree root)
{
	Tree pos;
	int k;
	for (int i = 0; i < N; i++)
	{
		k = 0;
		pos = root;
		Tree through[MAX_SIZE];
		while (pos != -1)
		{
			through[k++] = BTree[pos].data;
			if (BTree[pos].data == squ[i]){
				break;
			}
			else if(BTree[pos].data < squ[i]){
				pos = BTree[pos].Right;
			}
			else {
				pos = BTree[pos].Left;
			}
		}
		if (!check_squ(through, squ, k, i+1))	//查找穿过路径的所有节点是否全部存在于squ的前i+1个节点中, k有做++所以无需+1
			return false;
	}
	return true;
}

bool check_squ(Tree through[], Tree squ[], int how_long_through, int how_long_squ)
{
	bool flag;
	for (int i = 0; i < how_long_through; i++)
	{
		flag = false;
		for (int j = 0; j < how_long_squ; j++)
		{
			if (through[i] == squ[j]) {
				flag = true;
				break;
			}
		}
		if (flag == false)
			return false;
	}
	return true;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值