给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{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
 
此题我参考的是这篇文章的思路:【pta7-4 】是否同一棵二叉搜索树
我的具体代码如下:简单地说就是将一组数据置入二叉搜索树,将后续的测试数据一一比对。
//是否同一棵二叉搜索树
//思路:建立一棵树 ,与另一个要比较的序列进行比较
//建好树之后,从要比较的序列中按顺序的,一个接一个的在树中查找
//沿途给找到的树上的结点的标志域设置1
//当在树上查找序列中的某个数时,发现沿途中树有一个结点的标志域不是1 
//就说明在找上一个数之前,没有之前经过这个结点,
//就可以判断出这个序列的结构和树的结构不同
#include<stdio.h>
#include<stdlib.h>
/*二叉树的表示(传统结构体表示方法)*/ 
struct TreeNode
{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
	int flag;//判断是否遍历到
};
typedef struct TreeNode* tree;
tree t;
/*创建二叉树*/
tree makeTree(int n);
tree NewNode(int v);
tree Insert(tree t, int v);
/*判断*/
int JudgeTree(tree t, int n);
int check(tree t, int v);//查‘1’
void Reset(tree t);//重置flag
/*销毁二叉树*/
void FreeTree(tree t);
int main()
{
	int n, l, i;
	scanf("%d", &n);
	while (n)
	{
		scanf("%d", &l);
		t = makeTree(n);
		for (i = 0; i < l; i++)
		{
			if (JudgeTree(t, n))
				printf("Yes\n");
			else
				printf("No\n");
			Reset(t);
		}
		FreeTree(t);
		scanf("%d", &n);
	}
	return 0;
}
tree makeTree(int n)
{
	int i, v;
	scanf("%d", &v);
	/*先将第一个节点建好(根)*/
	t = NewNode(v);
	//再插入剩下的节点
	for (i = 1; i < n; i++)
	{
		scanf("%d", &v);
		t = Insert(t, v);
	}
	return t;
}
tree NewNode(int v)
{
	/*将数据包裹进一个节点*/
	t = (tree)malloc(sizeof(struct TreeNode));
	t->data = v;
	t->flag = 0;
	t->left = NULL;
	t->right = NULL;
	return t;
}
tree Insert(tree t, int v)
{
	if (!t)
		t = NewNode(v);
	//建立'根',(实质是递归搜索插入)
	else
	{
		if (v > t->data)
			//大右(以右孩子为‘根’递归搜索插入v)
			t->right = Insert(t->right, v);
		else
			//小左
			t->left = Insert(t->left, v);
	}
	return t;
}
/*判断*/
int JudgeTree(tree t, int n)
{
	int i = 0, v, flag = 0;
	scanf("%d", &v);
	if (v != t->data)
		flag = 1;
	else
		t->flag = 1;//相同树上标记置1
	for (i = 1; i < n; i++)
		//判断了根还剩下n-1个数
	{
		scanf("%d", &v);
		if (!check(t, v)&& !flag)
			flag = 1;
	}
	if (flag)
		return 0;//不是同一棵
	else
		return 1;
}
int check(tree t, int v)//返回1表示目前符合
{
	if (t->flag)//被标记为1 继续搜索
	{
		if (v > t->data)
			check(t->right, v);
		else if (v < t->data)
			check(t->left, v);
		else
//之前出现过该数字,再次出现说明不是同一棵
			return 0;
	}
	else//若未被标记为1,则需判断该节点是否为要找的值
	{
		if (v == t->data)
		{
			t->flag = 1;
			return 1;
		}
		else
			return 0;
	}
}
/*重置flag*/
void Reset(tree t)
{
	if (t->left)
		Reset(t->left);
	if (t->right)
		Reset(t->right);
	t->flag = 0;
}
void FreeTree(tree t)
{
	if (t->left)
		FreeTree(t->left);
	if (t->right)
		FreeTree(t->right);
	free(t);
} 
另外本题也可以使用静态链表(数组)来实现二叉搜索树。
实现方法如下:
//数组实现二叉搜索树(该方法不可录入数据0)
#include<stdio.h>
int tree[1025] = { 0 };
int main()
{
	int n,i,v,p;
	scanf("%d", &n);
	scanf("%d", &v);
	tree[1] = v;
	for (i = 1; i < n; i++)
	{
		scanf("%d", &v);
		p = 1;
		while (p<1025)
		{
			if (tree[p] == 0)//空位
			{
				tree[p] = v; break;
			}
			if (v>tree[p])//v大则在右子树上 右子树2*p+1
				p = 2 * p + 1;
			else if (v < tree[p])//左子树
				p = 2 * p;
			else//相同元素
				break;
		}
	}
	for (i = 0; i < 1025; i++)//层序遍历
	{
		if (tree[i])
		printf("%d\t", tree[i]);
	}
	return 0;
} 
                
                  
                  
                  
                  
      
          
                
                
                
                
              
                
                
                
                
                
              
                
                
              
            
                  
					269
					
被折叠的  条评论
		 为什么被折叠?
		 
		 
		
    
  
    
  
            


            