题目
给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{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
运行结果
0 | sample 换顺序。有Yes,有No:根不同,子树根不同。树有单边、有双子树 | Accepted | 4 ms | 384 KB |
1 | 最大N,多组合 | Accepted | 3 ms | 384 KB |
2 | N=1,只有1个节点 | Accepted | 2 ms | 364 KB |
3 | 卡只判断数字相对先后位置的错误算法 | Accepted | 2 ms | 296 KB |
程序
#include<iostream>
using namespace std;
//二叉搜索树结点定义
typedef struct TreeNode *Tree;
struct TreeNode{
int Element;
Tree Left, Right;
int flag;
};
Tree BuildTree(int N);
Tree NewNode(int Element);
Tree Insert(Tree T, int Element);
int Judge(Tree T, int N);
int check(Tree T, int Element);
void ResetT(Tree T);
void FreeTree(Tree T);
int main()
{
int N, L;
Tree T;
cin >> N;
while(N){
cin >> L;
T = BuildTree(N);
for(int i=0; i<L; i++){
if(Judge(T, N)) cout << "Yes\n";
else cout << "No\n";
ResetT(T); //清除T中的标记flag;
}
FreeTree(T);//释放动态内存(释放树)
cin >> N;
}
return 0;
}
Tree BuildTree(int N)
{
Tree T;
int Element;
//构建根结点
cin >> Element;
T = NewNode(Element);
for(int i=1; i<N; i++){
cin >> Element;
T = Insert(T, Element);
}
return T;
}
Tree NewNode(int Element)
{
Tree T = new TreeNode;
T->Element = Element;
T->Left = T->Right = NULL;
T->flag = 0;//表示未被遍历过的结点标记
return T;
}
Tree Insert(Tree T, int Element)
{
//当前结点为空时,申请新结点动态内存
if(!T) T = NewNode(Element);
else{
if(Element < T->Element) T->Left = Insert(T->Left, Element);
else T->Right = Insert(T->Right, Element);
}
return T;
}
int Judge(Tree T, int N)
{
int flag = 0;//0:代表目前一致,1:代表已经不一致->用来防止还没读完数据就跳出
int Element;
cin >> Element;
if(Element != T->Element) flag = 1;
else T->flag = 1;//1:表示已经遍历过了
for(int i=1; i<N; i++){
cin >> Element;
//只有当目前还一致时,才去进一判断
if( (!flag) && ( !check(T, Element))) flag = 1;
}
if(flag) return 0; //0:表示判断两树不一致
else return 1;
}
int check(Tree T, int Element)
{
if(T->flag){
//flag=1表示已经遍历过
if(Element < T->Element) return check(T->Left, Element);
else if(Element > T->Element) return check(T->Right, Element);
//若遍历了两次,且值相同,则两树不一致
else return 0;
}
else{
//当第一次遍历该结点,且元素相同时,则此结点保持一致
if(Element == T->Element){
T->flag = 1;
return 1;
}
//元素不同时,树不一致
else return 0;
}
}
void ResetT(Tree T)
{
if(T->Left) ResetT(T->Left);
if(T->Right) ResetT(T->Right);
T->flag = 0;
}
void FreeTree(Tree T)
{
if(T->Left) FreeTree(T->Left);
if(T->Right) FreeTree(T->Right);
delete T;
}