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

6512

被折叠的 条评论
为什么被折叠?



