题目

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

分析

总体思路是将每次插入序列直接插入,形成二叉搜索树,再遍历树看遍历结果是否一致
涉及到二叉树搜索树的插入,可以看看我写的 数据结构(五)二叉搜索树

#include<iostream>
#include<string>
#include<malloc.h>
using namespace std;
typedef struct TreeNode *BinTree;
struct TreeNode{
	int data;  // 存值
	BinTree left;  // 左子树
	BinTree right; // 右子树 
};

// 插入一个结点 
BinTree Insert(int x,BinTree BST){
	if(!BST){   // 如果结点为空,创建并返回 
		BST = (BinTree)malloc(sizeof(struct TreeNode));
		BST->data = x;
		BST->left = NULL;
		BST->right = NULL;
	}else{  // 如果结点不为空 
		if(x < BST->data)  // 如果 x 比当前结点的值小 
			BST->left = Insert(x,BST->left);  // 递归到左子树插入 
		else if(BST->data < x)  // 如果 x 比当前结点的值大 
			BST->right = Insert(x,BST->right);   // 递归到右子树插入
		// 如果相等,什么也不做 
	}
	return BST;
}

// 前序遍历 
void  PreOrderTraversal(BinTree BST,string &s){
	if(BST){
		s += BST->data+'0';  // 将结点值保存进字符串 
		PreOrderTraversal(BST->left,s);  // 进入左子树 
		PreOrderTraversal(BST->right,s);  // 进入右子树 
	}
}

int main(){
	int n,l;
	int tmp;
	cin>>n>>l;
	while(n){  // 当 n 不为空做循环 
		BinTree InitBST = NULL;
		string Initstr;
		// 每次新输入 n l 的初始插入序列 
		for(int i=0;i<n;i++){
			cin>>tmp;
			InitBST = Insert(tmp,InitBST);
		}
		// Initstr 记录初始插入序列形成的树的先序遍历结果 
		// 思考为什么不用中序记录? 
		PreOrderTraversal(InitBST,Initstr);
		
		// 后 l 行 
		for(int i=0;i<l;i++){
			BinTree BST = NULL;
			string str;
			for(int j=0;j<n;j++){
				cin>>tmp;
				BST = Insert(tmp,BST);
			}
			// 每行的插入序列产生一个树,用 str 记录先序遍历结果 
			PreOrderTraversal(BST,str);
			
			// 再将初始序列和每次插入序列产生的值进行对比 
			if(str == Initstr)
				cout<<"Yes"<<endl;
			else
				cout<<"No"<<endl;
		}
		cin>>n>>l;
	}
	return 0;
}