二叉树
《数据结构与算法》实践能力专题训练5 二叉树
A数据结构实验之二叉树一:树的同构
题目描述
Description
给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。
现给定两棵树,请你判断它们是否是同构的。
Input
输入数据包含多组,每组数据给出2棵二叉树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出”-”。给出的数据间用一个空格分隔。
注意:题目保证每个结点中存储的字母是不同的。
Output
如果两棵树是同构的,输出“Yes”,否则输出“No”。
Sample
Input
8
A 1 2
B 3 4
C 5 -
D - -
E 6 -
G 7 -
F - -
H - -
8
G - 4
B 7 6
F - -
A 5 1
H - -
C 0 -
D - -
E 2 -
Output
Yes
AC代码
#include <bits/stdc++.h>
#define null 11
using namespace std;
int n,m;
struct node
{
char data;
int l,r;
} tree1[1024],tree2[1024];
void creat(struct node root[],int n)
{
char c,c1,c2;
for(int i=0; i<n; i++)
{
cin>>c>>c1>>c2;
root[i].data=c;
if(c1!='-')root[i].l=c1-'0';
else root[i].l=null;
if(c2!='-')root[i].r=c2-'0';
else root[i].r=null;
}
}
int main()
{
while(cin>>n)
{
creat(tree1,n);
cin>>m;
creat(tree2,m);
int f=0,j;
for(int i=0; i<n; i++)
{
for(j=0; j<m; j++)
{
if(tree1[i].data==tree2[j].data)
{
if(tree1[tree1[i].l].data==tree2[tree2[j].r].data&&tree1[tree1[i].r].data==tree2[tree2[j].l].data)
break;
else if(tree1[tree1[i].l].data==tree2[tree2[j].l].data&&tree1[tree1[i].r].data==tree2[tree2[j].r].data)
break;
else
{
f++;
break;
}
}
}
if(j==m)
{
f++;
break;
}
}
if(f==0)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
B - 数据结构实验之二叉树二:遍历二叉树
题目描述
Description
已知二叉树的一个按先序遍历输入的字符序列,如abc,de,g,f, (其中,表示空结点)。请建立二叉树并按中序和后序的方式遍历该二叉树。
Input
连续输入多组数据,每组数据输入一个长度小于50个字符的字符串。
Output
每组输入数据对应输出2行:
第1行输出中序遍历序列;
第2行输出后序遍历序列。
Sample
Input
abc,de,g,f,
Output
cbegdfa
cgefdba
AC代码
#include <bits/stdc++.h>
#define null 11
using namespace std;
int x;
string s;
typedef struct node
{
char data;
struct node *l,*r;
}tree;
tree *creat()
{
tree *root;
if(s[x]==',')
{
x++;
return NULL;
}
else
{
root=new node;
root->data=s[x++];
root->l=creat();
root->r=creat();
}
return root;
}
void mid(tree *root)
{
if(root)
{
mid(root->l);
cout<<root->data;
mid(root->r);
}
}
void lat(tree *root)
{
if(root)
{
lat(root->l);
lat(root->r);
cout<<root->data;
}
}
int main()
{
while(cin>>s)
{
x=0;
tree *root;
root=creat();
mid(root);
cout<<endl;
lat(root);
cout<<endl;
}
return 0;
}
C - 数据结构实验之二叉树三:统计叶子数
题目描述
Description
已知二叉树的一个按先序遍历输入的字符序列,如abc,de,g,f, (其中,表示空结点)。请建立二叉树并求二叉树的叶子结点个数。
Input
连续输入多组数据,每组数据输入一个长度小于50个字符的字符串。
Output
输出二叉树的叶子结点个数。
Sample
Input
abc,de,g,f,
Output
3
AC代码
#include <bits/stdc++.h>
#define null 11
using namespace std;
int x,sum;
string s;
typedef struct node
{
char data;
struct node *l,*r;
}tree;
tree *creat()
{
tree *root;
if(s[x]==',')
{
x++;
return NULL;
}
else
{
root=new node;
root->data=s[x++];
root->l=creat();
root->r=creat();
}
return root;
}
void yezi(tree *root)
{
if(root)
{
if(root->l==NULL&&root->r==NULL)
sum++;
yezi(root->l);
yezi(root->r);
}
}
int main()
{
while(cin>>s)
{
x=0;
sum=0;
tree *root;
root=creat();
yezi(root);
cout<<sum<<endl;
}
return 0;
}
D - 数据结构实验之二叉树四:(先序中序)还原二叉树
题目描述
Description
给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。
Input
输入数据有多组,每组数据第一行输入1个正整数N(1 <= N <= 50)为树中结点总数,随后2行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区分大小写)的字符串。
Output
输出一个整数,即该二叉树的高度。
Sample
Input
9
ABDFGHIEC
FDHGIBEAC
Output
5
AC代码
#include <bits/stdc++.h>
using namespace std;
int n;
char a[1100],b[1100];
typedef struct node
{
struct node *l,*r;
char data;
} tree;
tree *Creat(int n,char *a,char *b)
{
if(n==0)return NULL;
tree *root=new node;
int i;
for(i=0; i<n; i++)
if(b[i]==a[0])break;
root->l=Creat(i,a+1,b);
root->r=Creat(n-1-i,a+i+1,b+i+1);
return root;
}
int high(tree*root)
{
int hl,hr,maxx;
if(root)
{
hl=high(root->l);
hr=high(root->r);
maxx=max(hr,hl);
return maxx+1;
}
else return 0;
}
int main()
{
while(cin>>n)
{
cin>>a>>b;
tree *root=new node;
root=Creat(n,a,b);
cout<<high(root)<<endl;
}
return 0;
}
E - 数据结构实验之二叉树五:层序遍历
题目描述
Description
已知一个按先序输入的字符序列,如abd,eg,cf,(其中,表示空结点)。请建立二叉树并求二叉树的层次遍历序列。
Input
输入数据有多行,第一行是一个整数t (t<1000),代表有t行测试数据。每行是一个长度小于50个字符的字符串。
Output
输出二叉树的层次遍历序列。
Sample
Input
2
abd,eg,cf,
xnl,i,u,
Output
abcdefg
xnuli
AC代码
#include<bits/stdc++.h>
using namespace std;
char s[55];
int sum,a;
typedef struct node
{
char data;
struct node *r,*l;
} tree;
tree* Create()
{
tree*root;
char c;
c=s[a++];
if(c==',')
{
root=NULL;
return 0;
}
else
{
root=new node;
root->data=c;
root->l=Create();
root->r=Create();
}
return root;
}
void cengxu(tree *root)
{
queue<tree*>q;
q.push(root);
while(!q.empty())
{
if(q.front())
{
cout<<q.front()->data;
q.push(q.front()->l);
q.push(q.front()->r);
}
q.pop();
}
}
int main()
{
int t;
cin>>t;
getchar();
while(t--)
{
cin>>s;
tree* root;
a=0;
root=Create();
cengxu(root);
cout<<endl;
}
}
F - 数据结构实验之二叉树六:哈夫曼编码
题目描述
Description
字符的编码方式有多种,除了大家熟悉的ASCII编码,哈夫曼编码(Huffman Coding)也是一种编码方式,它是可变字长编码。该方法完全依据字符出现概率来构造出平均长度最短的编码,称之为最优编码。哈夫曼编码常被用于数据文件压缩中,其压缩率通常在20%~90%之间。你的任务是对从键盘输入的一个字符串求出它的ASCII编码长度和哈夫曼编码长度的比值。
Input
输入数据有多组,每组数据一行,表示要编码的字符串。
Output
对应字符的ASCII编码长度la,huffman编码长度lh和la/lh的值(保留一位小数),数据之间以空格间隔。
Sample
Input
AAAAABCD
THE_CAT_IN_THE_HAT
Output
64 13 4.9
144 51 2.8
Hint
AC代码
F - 数据结构实验之二叉树六:哈夫曼编码
题目描述
Description
字符的编码方式有多种,除了大家熟悉的ASCII编码,哈夫曼编码(Huffman Coding)也是一种编码方式,它是可变字长编码。该方法完全依据字符出现概率来构造出平均长度最短的编码,称之为最优编码。哈夫曼编码常被用于数据文件压缩中,其压缩率通常在20%~90%之间。你的任务是对从键盘输入的一个字符串求出它的ASCII编码长度和哈夫曼编码长度的比值。
Input
输入数据有多组,每组数据一行,表示要编码的字符串。
Output
对应字符的ASCII编码长度la,huffman编码长度lh和la/lh的值(保留一位小数),数据之间以空格间隔。
Sample
Input
AAAAABCD
THE_CAT_IN_THE_HAT
Output
64 13 4.9
144 51 2.8
AC代码
#include <bits/stdc++.h>
#define null 11
using namespace std;
string s;
int main()
{
while(cin>>s)
{
int n=0;
double sum1=0,sum2=0;
int a[256]= {0};
int b[11000]= {0};
int l=s.length();
for(int i=0; i<l; i++)
a[(int)s[i]]++;
sum1=8*l;
for(int i=0;i<256;i++)
if(a[i]!=0)b[n++]=a[i];
int top=0,rear=n-1;
while(top<rear)
{
sort(b+top,b+n);
int x1=b[top++];
int x2=b[top++];
b[--top]=x1+x2;
sum2+=x1+x2;
}
printf("%.0lf %.0lf %.1lf\n",sum1,sum2,sum1/sum2);
}
return 0;
}
G - 数据结构实验之二叉树七:叶子问题
题目描述
Description
已知一个按先序输入的字符序列,如abd,eg,cf,(其中,表示空结点)。请建立该二叉树并按从上到下从左到右的顺序输出该二叉树的所有叶子结点。
Input
输入数据有多行,每一行是一个长度小于50个字符的字符串。
Output
按从上到下从左到右的顺序输出二叉树的叶子结点。
Sample
Input
abd,eg,cf,
xnl,i,u,
Output
dfg
uli
AC代码
#include<bits/stdc++.h>
using namespace std;
string s;
int x;
typedef struct node
{
char data;
struct node *r,*l;
} tree;
tree* creat()
{
tree *root;
if(s[x]==',')
{
x++;
return NULL;
}
else
{
root=new node;
root->data=s[x++];
root->l=creat();
root->r=creat();
}
return root;
}
void findd(tree *root)
{
tree *a[110000];
int top=0,rear=0;
a[rear++]=root;
while(top<rear)
{
if(a[top])
{
if(a[top]->l==NULL&&a[top]->r==NULL)
cout<<a[top]->data;
if(a[top]->l)a[rear++]=a[top]->l;
if(a[top]->r)a[rear++]=a[top]->r;
}
top++;
}
}
int main()
{
while(cin>>s)
{
x=0;
tree *root;
root=creat();
findd(root);
cout<<endl;
}
return 0;
}
H - 数据结构实验之二叉树八:(中序后序)求二叉树的深度
题目描述
Description
已知一颗二叉树的中序遍历序列和后序遍历序列,求二叉树的深度。
Input
输入数据有多组,输入T,代表有T组数据。每组数据包括两个长度小于50的字符串,第一个字符串表示二叉树的中序遍历,第二个表示二叉树的后序遍历。
Output
输出二叉树的深度。
Sample
Input
2
dbgeafc
dgebfca
lnixu
linux
Output
4
3
AC代码
#include<bits/stdc++.h>
using namespace std;
string s;
char a[10111],b[10111];
int x;
typedef struct node
{
char data;
struct node *r,*l;
} tree;
tree* creat(int n,char* mid,char* lat)
{
if(n==0)
return NULL;
else
{
tree *root=new node;
int i;
for(i=0; i<n; i++)
if(mid[i]==lat[n-1])break;
root->data=mid[i];
root->l=creat(i,mid,lat);
root->r=creat(n-i-1,mid+1+i,lat+i);
return root;
}
}
int high(tree *root)
{
int hr,hl,maxx;
if(root)
{
hl=high(root->l);
hr=high(root->r);
maxx=max(hl,hr);
return maxx+1;
}
else
return 0;
}
void findd(tree *root)
{
tree *a[110000];
int top=0,rear=0;
a[rear++]=root;
while(top<rear)
{
if(a[top])
{
if(a[top]->l==NULL&&a[top]->r==NULL)
cout<<a[top]->data;
if(a[top]->l)a[rear++]=a[top]->l;
if(a[top]->r)a[rear++]=a[top]->r;
}
top++;
}
}
int main()
{
int n;
cin>>n;
while(n--)
{
cin>>a>>b;
int len=strlen(a);
tree *root=new node;
root=creat(len,a,b);
cout<<high(root)<<endl;
}
return 0;
}
I - 二叉树
题目描述
Description
已知二叉树的一个按前序遍历输入的字符序列,如abc,de,g,f, (其中,表示空结点)。请建立二叉树,并输出建立二叉树的前序遍历序列、中序遍历序列、后序遍历序列、层次遍历序列、深度、叶子数。
Input
多组测试数据,对于每组测试数据,输入一个长度小于50的按前序遍历输入的字符序列。
Output
对于每组测试数据,第1行输出其前序遍历序列、第2行输出其中序遍历序列、第3行输出其后序遍历序列、第4行输出其深度、第5行输出其叶子数。
Sample
Input
abc,de,g,f,
Output
abcdegf
cbegdfa
cgefdba
abcdefg
5
3
AC代码
#include <bits/stdc++.h>
using namespace std;
struct node
{
char data;
node *l,*r;
};
char a[55];
int i,h1,num1;
struct node *creat()
{
struct node *root;
if(a[i]==',')
{
i++;
root=NULL;
}
else
{
root=(struct node*)malloc(sizeof(struct node));
root->data=a[i++];
root->l=creat();
root->r=creat();
}
return root;
};
void fir(node *root)
{
if(root)
{
cout<<root->data;
fir(root->l);
fir(root->r);
}
}
void mid(node *root)
{
if(root)
{
mid(root->l);
cout<<root->data;
mid(root->r);
}
}
void endd(node *root)
{
if(root)
{
endd(root->l);
endd(root->r);
cout<<root->data;
}
}
void f(node *root)
{
node *t[55];
int ll=0,rr=0;
t[rr++]=root;
while(rr>ll)
{
if(t[ll])
{
cout<<t[ll]->data;
t[rr++]=t[ll]->l;
t[rr++]=t[ll]->r;
}
ll++;
}
}
int h(node *root)
{
if(!root)
h1=0;
else
h1=max(h(root->l),h(root->r))+1;
return h1;
}
node *num(node *root)
{
if(root)
{
if(!root->l&&!root->r)
num1++;
num(root->l);
num(root->r);
}
return root;
}
int main()
{
while(cin>>a)
{
node *root;
i=0;
h1=0;
num1=0;
root=creat();
fir(root);
cout<<endl;
mid(root);
cout<<endl;
endd(root);
cout<<endl;
f(root);
cout<<endl;
cout<<h(root)<<endl;
num(root);
cout<<num1<<endl;
}
return 0;
}
J - 迷失の搜索树
题目描述
Description
小璐在机缘巧合之下获得了一个二叉搜索树,这个二叉搜索树恰好有n个节点,每个节点有一个权值,每个节点的权值都在[1,n]这个区间内,并且两两不相同,真是优美的性质啊
但是命运的不公又让她失去了这个二叉搜索树
幸运的是,她还记得自己丢失的二叉搜索树的前序遍历序列。
在丢了二叉搜索树之后,小璐无比想念她的这个树的后序遍历
那么问题来了,聪明的你在知道这个二叉搜索树的前序遍历的序列的情况下,能帮她找到这个二叉搜索树的后序遍历嘛?
Input
多组输入,以文件结尾
每组数据第一行为一个整数n,代表这个二叉搜索树的节点个数(1<=n<=100)
接下来一行n个整数,代表这个二叉搜索树的前序遍历序列
Output
输出n个整数
表示这个二叉树的后序遍历序列
Sample
Input
5
4 2 1 3 5
Output
1 3 2 5 4
Hint
二叉查找树是一棵空树,或者是具有下列性质的二叉树:
若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值
若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值
它的左、右子树也分别为二叉排序树
AC代码
#include <bits/stdc++.h>
#define null 11
using namespace std;
typedef struct node
{
int data;
struct node *l,*r;
} tree;
string s;
int n,flag;
int a[1100];
tree* creat(tree *root,int x)
{
if(root==NULL)
{
root=new node;
root->data=x;
root->l=NULL;
root->r=NULL;
}
else
{
if(root->data>x)
root->l=creat(root->l,x);
else
root->r=creat(root->r,x);
}
return root;
}
void lat(tree *root)
{
if(root)
{
lat(root->l);
lat(root->r);
if(!flag)
{
flag++;
cout<<root->data;
}
else cout<<" "<<root->data;
}
}
int main()
{
while(cin>>n)
{
flag=0;
tree *root=NULL;
for(int i=0; i<n; i++)
{
int x;
cin>>x;
root=creat(root,x);
}
lat(root);
cout<<endl;
}
return 0;
}
K - 巨斧砍大树
题目描述
Description
阿福最近练就了一个新的招式:巨斧砍大树。这个招式可以砍掉一颗二叉搜索树的某个子树。现在,阿福面前有一颗 nn 个结点的二叉搜索树,他要使用 mm 次招式,于是他想询问你每次使用「巨斧砍大树」后二叉搜索树会被砍成什么样子。
二叉搜索树或者是一棵空树,或者是具有下列性质的二叉树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;它的左、右子树也分别为二叉搜索树。
Input
第一行输入 22 个整数 nn, mm (1 \leqslant n, m \leqslant 10)(1⩽n,m⩽10)。表示二叉搜索树的结点个数和招式使用次数。
第二行输入 nn 个空格隔开的整数 vv (1 \leqslant v \leqslant 10)(1⩽v⩽10),表示二叉搜索树是以此序列顺序插入生成的二叉树(保证互不相同)。
接下来输入 mm 行,每行一个整数 ww (1 \leqslant w \leqslant 10)(1⩽w⩽10),表示阿福要砍掉结点上数值为 ww 的子树(保证 ww 是初始二叉树上存在的数值)。
Output
对于每次砍树,如果成功砍掉子树,则先输出一行 Cut x,其中 xx 为被砍掉子树的根节点上的数值。如果要砍掉的结点在之前已被砍掉,则输出一行 Already cut x,xx 的含义同上。
随后输出一行,表示此次砍树结束后当前二叉树的中序遍历结果,以空格分隔(行末没有多余空格,如果整颗二叉树已为空,则输出一行空行)。
Sample
Input
5 5
1 3 2 4 5
5
2
3
4
1
Output
Cut 5
1 2 3 4
Cut 2
1 3 4
Cut 3
1
Already cut 4
1
Cut 1
AC代码
#include <bits/stdc++.h>
using namespace std;
int n,sum,m;
typedef struct node
{
int data;
struct node *l,*r;
} tree;
tree *creat(tree *root,int x)
{
if(root==NULL)
{
root=new node;
root->data=x;
root->r=root->l=NULL;
return root;
}
else
{
if(root->data>x)
root->l=creat(root->l,x);
else
root->r=creat(root->r,x);
}
return root;
}
tree *Del(tree *root,int x)
{
if(!root)
cout<<"Already cut "<<x<<endl;
else
{
if(x==root->data)
{
cout<<"Cut "<<x<<endl;
root=NULL;
}
else if(x<root->data)
root->l=Del(root->l,x);
else
root->r=Del(root->r,x);
}
return root;
}
void mid(tree *root)
{
if(root)
{
mid(root->l);
if(sum==0)cout<<root->data;
else cout<<" "<<root->data;
sum++;
mid(root->r);
}
}
int main()
{
cin>>n>>m;
tree *root=NULL;
for(int i=0; i<n; i++)
{
int x;
cin>>x;
root=creat(root,x);
}
for(int i=0; i<m; i++)
{
sum=0;
int m;
cin>>m;
root=Del(root,m);
mid(root);
cout<<endl;
}
return 0;
}
说明
终于写完了,有史以来最长的一篇博客,这些就是所谓的模板题。
用C太费劲了,都是用C++写的,干就完事了,二叉树冲冲冲!!!