数据结构—— 树:是否同一棵二叉搜索树
Posted 大彤小忆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构—— 树:是否同一棵二叉搜索树相关的知识,希望对你有一定的参考价值。
题意理解:
⋆
\\star
⋆ 给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如,按照序列{2,1,3}和{2,3,1}插入初始为空的二叉搜索树,都得到一样的结果。
⋆
\\star
⋆ 问题: 对于输入的各种插入序列,需要判断它们是否能生成一样的二叉搜索树。
输入样例: 输入样例第一行的4 2
中4
代表第一组的二叉搜索树有4个结点,2
代表后面有两棵树需要与前面比较是否一样;第二行3 1 4 2
代表输入的第一组序列;后面的第三四行代表需要与第一组序列比较是否一样的若干组序列。第五行的2 1
中4
代表第二组的二叉搜索树有2个结点,1
代表后面有一棵树需要与前面比较是否一样;第六行2 1
代表输入的第二组序列;后面的第七行代表需要与第二组序列比较是否一样的若干组序列。第八行0
代表结束比较,退出程序。
求解思路: 两个序列是否对应相同搜索树的判别。
1. 分别建两棵搜索树的判别方法
⋄
\\diamond
⋄ 根据两个序列分别建树,再判别树是否一样
2. 不建树的判别方法
3. 建一棵树,再判别其他序列是否与该树一致
① 搜索树表示
② 建搜索树T
③ 判别一序列是否与搜索树T一致
搜索树表示:
typedef struct TreeNode *Tree;
struct TreeNode {
int v; //用v表示结点的信息
Tree Left, Right; //用链表形式表示树
int flag; //flag为某个结点是否被访问过的标志,用来判别一个序列是否与树一样,如果某个结点未被访问,flag=0,否则flag=1
};
程序框架搭建:
int main()
{
对每组数据
∙读入N和L
∙根据第一行序列建树T
·依据树T分别判别后面的L个序列是否能与T形成同一搜索树并输出结果
return 0;
}
需要设计的函数: 1. 读数据建搜索树T
2. 判别序列是否与T构成一样的搜索树
int main()
{
int N, L;
Tree T;
cin >> N;
while(N){
cin >> L;
T = Make Tree(N);
for (int i = 0; i < L; i++)
{
if (Judge(T, N))
cout<< "是" << endl;
else
cout<< "否" << endl;
ResetT(T); //清除T中的标记flag
}
Free Tree(T);
cin >> N;
}
return 0;
}
如何判别:
问题: 如何判别序列3 2 4 1是否与树T一致?
方法: 在树T中按顺序搜索序列3 2 4 1中的每个数,如果每次搜索所经过的结点在前面均出现过,则一致;否则如果某次搜索中遇到前面未出现的结点,则不一致。
判断是否同一棵二叉搜索树的完整实现代码如下所示。
#include<iostream>
using namespace std;
/*
题目:对于不同的输入序列,判断是否为同一个二叉搜索树。
求解思路:
1、搜素树表示;
2、建搜索树T;
3、判断一序列是否与搜索树T一致。
*/
//搜索树表示
typedef struct TreeNode *Tree;
struct TreeNode
{
int v; //用v表示结点的信息
Tree Left, Right; //用链表形式表示树
int flag; //flag为某个结点是否被访问过的标志,用来判别一个序列是否与树一样,如果某个结点未被访问,flag=0,否则flag=1
};
Tree MakeTree(int N);
Tree NewNode(int V);
Tree Insert(Tree T, int V);
int Judge(Tree T, int N);
void ResetT(Tree T);
void FreeTree(Tree T);
//程序框架搭建
int main()
{
int N, L; // N个结点,L个序列
Tree T;
cin >> N;
while (N)
{
cin >> L;
T = MakeTree(N); //根据第一行序列建N个结点的树T
for (int i = 0; i < L; i++) //依据树T分别判别后面的L个序列是否能与T形成同一搜索树并输出结果
{
if (Judge(T, N))
cout << "是" << endl;
else
cout << "否" << endl;
ResetT(T); //清除T中的标记flag
}
FreeTree(T);
cin >> N;
}
system("pause");
return 0;
}
//如何构建搜索树
Tree MakeTree(int N)
{
Tree T;
int V;
cin >> V; //首先读入第一个元素放入V中
T = NewNode(V); //为T构造新结点
for (int i = 1; i < N; i++)
{
cin >> V; //依次读入序列后面的元素
T = Insert(T, V); //读入的后面元素依次插入树T
}
return T;
}
//建新结点(一般为第一个结点)
Tree NewNode(int V)
{
Tree T = (Tree)malloc(sizeof(struct TreeNode));
T->v = V;
T->Left = T->Right = NULL;
T->flag = 0;
return T;
}
//后续结点的插入
Tree Insert(Tree T, int V)
{
if (!T) //T为空
{
T = NewNode(V); //通过NewNode(V)为T构造第一个结点
}
else //T不为空
{
if (V > T->v)
T->Right = Insert(T->Right, V);
else
T->Left = Insert(T->Left, V);
}
return T;
}
//如何判别(已经访问过的结点要进行标记,使flag=1)
//在树T中按顺序搜索序列中的每个数,如果每次搜索所经过的结点在前面均出现过,则一致;
// 否则如果某次搜索中遇到前面未出现的结点,则不一致。
int check(Tree T, int V)
{
if (T->flag) //某个结点被访问过(因为之前的V == T->v,才使得flag =1)
{
if (V < T->v)
return check(T->Left, V);
else if (V > T->v)
return check(T->Right, V);
else //如果V == T->v,意味着这个序列中有两个元素出现了两次以上,即重复出现,认为不一致
return 0;
}
else //某个结点未被访问过
{
if (V == T->v) //如果未被访问过的结点刚好是所搜索的,使flag=1
{
T->flag = 1;
return 1;
}
else //否则未被访问过的结点不是所搜索的,即遇到前面未出现的结点,使flag=0
return 0;
}
}
int Judge(Tree T, int N)
{
int V, same = 1;
//same:1代表目前还一致,0代表已经不一致
cin >> V;
if (V != T->v) //序列第一个元素与T的根结点不一致
same = 0; //两棵树已经不一致
else
T->flag = 1;
for (int i = 1; i < N; i++)
{
cin >> V;
if ((same) && (!check(T, V)))
same = 0;
}
if (!same)
return 0;
else
return 1;
}
//清除T中各个结点的标记
void ResetT(Tree T)
{
if (T->Left)
ResetT(T->Left);
if (T->Right)
ResetT(T->Right);
T->flag = 0;
}
//释放T的空间
void FreeTree(Tree T)
{
if (T->Left)
FreeTree(T->Left);
if (T->Right)
FreeTree(T->Right);
free(T);
}
运行上述代码,进行测试。
输入如下所示。
4 2
3 1 4 2
3 4 1 2
3 2 4 1
2 1
2 1
1 2
0
代码运行输出的测试效果如下图所示。
以上是关于数据结构—— 树:是否同一棵二叉搜索树的主要内容,如果未能解决你的问题,请参考以下文章