#数据结构与算法学习笔记#PTA12:二叉搜索树判断(C/C++)

2018.4.20

这道题有两个思路,一是根据两个序列分别建二叉搜索树,再根据二叉树的判别方法判别两棵树是否为同一棵树;二是建立其中一棵二叉搜索树,将待检验序列的元素依次进行搜索,若为同一棵二叉搜索树,则每次在树中搜索所访问过的结点应当在序列该数搜索到之前都访问过。

如对于3 1 4 2所建成的二叉搜索树T来说,将待检验序列3 4 1 2依次搜索,当搜索至2时,341三个结点应当都被访问过。而对于序列3 2 4 1,当搜索2时,存在未访问过的结点1,因此两者不是同一棵二叉搜索树。


原题:

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。

输入格式:

输入包含若干组测试数据。每组数据的第1行给出两个正整数N (≤10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。最后L行,每行给出N个插入的元素,属于L个需要检查的序列。

简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。

输出格式:

对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。


以下是实现代码:

// IsSameBinarySearchTree.cpp: 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <vector>

using namespace std;

//二叉树结点类
class TreeNode {
public:
	int value;
	TreeNode* left;
	TreeNode* right;
	bool isvisit;			//标志这个结点是否访问过
};
typedef TreeNode* Tree;


void Init();
Tree MakeTree(int length);
Tree NewNode(int value);
Tree Insert(Tree tree, int value);
bool Judge(Tree tree, int length);		//不建树的判断方法
bool Check(Tree tree, int value);
void Reset(Tree tree);					//清除标记
void Free(Tree tree);

int main()
{

	Init();

	system("pause");
	return 0;
}

void Init() {

	int length;			//待查验序列结点数
	int num;			//待查验序列数
	Tree tree;

	cin >> length;
	if (length == 0) return;

	while (length) {

		cin >> num;		
		tree = MakeTree(length);

		for (int i = 0; i < num; i++) {
			if (Judge(tree, length)) {
				cout << "Yes" << endl;
			}
			else
			{
				cout << "No" << endl;
			}

			Reset(tree);
		}

		Free(tree);
		cin >> length;
	}

}

Tree MakeTree(int length) {
	Tree tree;
	int value;

	cin >> value;
	tree = NewNode(value);

	for (int i = 1; i < length; i++) {
		cin >> value;
		tree = Insert(tree, value);
	}
	return tree;
}

Tree NewNode(int value) {
	Tree tree = new TreeNode;
	tree->value = value;
	tree->left = NULL;
	tree->right = NULL;
	tree->isvisit = false;
	return tree;
}

Tree Insert(Tree tree, int value) {
	if (!tree)tree = NewNode(value);
	else {
		//若新插入结点值大于当前结点值,递归插入右子树
		if (value > tree->value) {
			tree->right = Insert(tree->right, value);
		}
		//若新插入结点值小于当前结点值,递归插入左子树
		else {
			tree->left = Insert(tree->left, value);
		}
	}
	return tree;
}


bool Judge(Tree tree, int length) {
	//若每次用当前二叉搜索树对待检验序列进行搜索,若每次在树中搜索所访问过的结点在序列该数之前都出现过,则为同一搜索树
	bool isSameTree = true;
	int value;

	cin >> value;
	if (value != tree->value)isSameTree = false;
	else tree->isvisit = true;

	for (int i = 1; i < length; i++) {
		cin >> value;
		//查验每次在树中搜索所访问过的结点在序列该数之前都出现过(即使判断结束,也要保证数据读完)
		if (isSameTree && (!Check(tree, value)))
			isSameTree = false;
	}
	
	return isSameTree;
}

bool Check(Tree tree, int value) {
	if (tree->isvisit) {
		//若该结点已经被访问过,递归搜索检查左子树或右子树
		if (value < tree->value)return Check(tree->left, value);
		else if (value > tree->value)return Check(tree->right, value);
		else return false;
	}
	else {
		//若第一个未访问过的结点为该结点,则返回true
		if (value == tree->value) {
			tree->isvisit = true;
			return true;
		}
		else return false;
	}
}

void Reset(Tree tree) {
	if (tree->left)Reset(tree->left);
	if (tree->right)Reset(tree->right);
	tree->isvisit = false;
}

void Free(Tree tree) {
	if (tree->left)Free(tree->left);
	if (tree->right)Free(tree->right);
	delete tree;
}

猜你喜欢

转载自blog.csdn.net/qq_20304723/article/details/80025254