数据结构实验之查找一:二叉排序树
Time Limit: 400MS Memory limit: 65536K
题目描述
对应给定的一个序列可以唯一确定一棵二叉排序树。然而,一棵给定的二叉排序树却可以由多种不同的序列得到。例如分别按照序列{3,1,4}和{3,4,1}插入初始为空的二叉排序树,都得到一样的结果。你的任务书对于输入的各种序列,判断它们是否能生成一样的二叉排序树。
输入
输入包含若干组测试数据。每组数据的第1行给出两个正整数N (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
提示
在二叉排序树中删去一个结点,分三种情况讨论:
1.若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。
2.若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉排序树的特性。
3.若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整。比较好的做法是,找到*p的直接前驱(或直接后继)*s,用*s来替换结点*p,然后再删除结点*s。

/* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素结点, */
/* 并返回TRUE;否则返回FALSE。 */
Status DeleteBST(BiTree *T,int key)
{
if(!T) /* 不存在关键字等于key的数据元素 */
return FALSE;
else
{
if (key==T->data) /* 找到关键字等于key的数据元素 */
return Delete(T);
else if (key<T->data)
return DeleteBST(T->lchild,key);
else
return DeleteBST(T->rchild,key);
}
}
/* 从二叉排序树中删除结点p,并重接它的左或右子树。 */
Status Delete(BiTree *p)
{
BiTree *q,*s;
if(p->rchild==NULL) /* 右子树空则只需重接它的左子树(待删结点是叶子也走此分支) */
{
q=p; p=p->lchild; free(q);
}
else if(p->lchild==NULL) /* 只需重接它的右子树 */
{
q=p;p=p->rchild; free(q);
}
else /* 左右子树均不空 */
{
q=p; s=p->lchild;
while(s->rchild) /* 转左,然后向右到尽头(找待删结点的前驱) */
{
q=s;
s=s->rchild;
}
p->data=s->data; /* s指向被删结点的直接前驱(将被删结点前驱的值取代被删结点的值) */
if(q!=p)
q->rchild=s->lchild; /* 重接q的右子树 */
else
q->lchild=s->lchild; /* 重接q的左子树 */
free(s);
}
return TRUE;
}#include<bits/stdc++.h>
using namespace std;
int n,m,a[1000100],num=0;
struct node
{
int data;
node *L,*R;
};
node *Creat()
{
node *p=new node;
p->L=NULL;
p->R=NULL;
return p;
}
void BSTInsert(node *&root,int element) //插入算法
{
if(root==NULL)
{
root=Creat();
root->data=element;
return ;
}
if(element<root->data)
BSTInsert(root->L,element);
else
BSTInsert(root->R,element);
return ;
}
void Build(node *&root) //创建二叉树
{
root=NULL; //勿忘,否则没法插入第一个元素。
for(int i=0;i<n;i++)
{
BSTInsert(root,a[i]);
}
}
//int mid(node*p)
//{
// if(p)
// {
// printf("%d ",p->data);
// mid(p->L);
// mid(p->R);
// }
//}
int Judge(node* root,node *Root)
{
if(!root&&!Root)
return 1;
if(root&&Root)
{
if(root->data!=Root->data)
return 0;
if(Judge(root->L,Root->L)&&Judge(root->R,Root->R))
{
num++;
}
else
return 0;
}
else
return 0;
}
int main()
{
while(~scanf("%d",&n))
{
if(n==0)
break;
scanf("%d",&m);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
node *Root=Creat();
Build(Root);
//mid(Root);
for(int i=0;i<m;i++)
{
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
node *root=Creat();
Build(root);
num=0;
Judge(root,Root);
if(num==n)
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}
///新代码风格。。、#include<bits/stdc++.h>
#define bug() puts("*****************");
using namespace std;
const int maxn = 1100;
int n,m,top=0;
int a[100],temp[100];
struct node{
int val;
node *L,*R;
};
node *Create(int elem){
node *p=new node;
p->val=elem;
p->L=p->R=NULL;
return p;
}
void Build(node *&p,int elem){
if(!p) p=Create(elem);
else {
if(p->val>elem) Build(p->L,elem);
else Build(p->R,elem);
}
}
bool judge(node *root,node *p){
if(!root&&!p) return true;
if(p&&root) return root->val==p->val&&judge(root->L,p->L)&&judge(root->R,p->R);
return false;
}
int main(){
top=0;
while(scanf("%d",&n),n){
scanf("%d",&m);
node *root=NULL;
for(int i=0;i<n;i++){
int t;
scanf("%d",&t);
Build(root,t);
}
//mid(0);
while(m--){
node *p=NULL;
for(int i=0;i<n;i++){
int t;
scanf("%d",&t);
Build(p,t);
}
puts(judge(root,p)?"Yes":"No");
}
}
return 0;
}

本文探讨如何通过序列生成二叉排序树,并通过比较不同序列生成的树来判断其是否相同。涉及二叉排序树的基本操作和序列比较。
1521

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



