目录
完全二叉树的层序遍历
一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于深度为 D 的,有 N 个结点的二叉树,若其结点对应于相同深度完美二叉树的层序遍历的前 N 个结点,这样的树就是完全二叉树。
给定一棵完全二叉树的后序遍历,请你给出这棵树的层序遍历结果。
输入格式:
输入在第一行中给出正整数 N(≤30),即树中结点个数。第二行给出后序遍历序列,为 N 个不超过 100 的正整数。同一行中所有数字都以空格分隔。
输出格式:
在一行中输出该树的层序遍历序列。所有数字都以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
8
91 71 2 34 10 15 55 18
输出样例:
18 34 55 71 2 10 15 91
#include<stdio.h>
int a[31],n;
void f(int x){
if(x>n)return ;
f(2*x);
f(2*x+1);
scanf("%d",&a[x]);
}
int main(){
//int n;
scanf("%d",&n);
f(1);
printf("%d",a[1]);
for(int i=2;i<=n;i++)
{
printf(" %d",a[i]);
}
return 0;
}
还原二叉树
给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。
输入格式:
输入首先给出正整数N(≤50),为树中结点总数。下面两行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。
输出格式:
输出为一个整数,即该二叉树的高度。
输入样例:
9
ABDFGHIEC
FDHGIBEAC
输出样例:
5
#include<stdio.h>
#include<math.h>
int creat(char *a,char *b,int n){//传的是地址
if(n<=0)return 0;
int i;
for(i=0;i<n;i++){
if(a[0]==b[i])
break;
}
int left=creat(&a[1],b,i);//(树在先序遍历中的位置,树在中序遍历中的位置,树的长度)
int right=creat(&a[i+1],&b[i+1],n-1-i);
return fmax(left,right)+1;//子树的最大高度+1
}
int main(){
int i,n;
scanf("%d",&n);
char a[51],b[51];
scanf("%s%s",a,b);
int c=creat(a,b,n);
printf("%d",c);
return 0;
}
树层次遍历
我们已知二叉树与其自然对应的树相比,二叉树中结点的左孩子对应树中结点的左孩子,二叉树中结点的右孩子对应树中结点的右兄弟。进而我们可以利用“基于带空指针信息的先根序列构建二叉树”的方法来构建其对应的树的左孩子-右兄弟存储结构。如8 5 1 0 6 0 2 0 0 3 4 0 0 7 0 0 0对应图1(a)所示的树,1 2 0 3 0 4 0 0 0对应如图1(b)所示的树。
请编写程序用上述方法构建树,并给出树的层次遍历序列。
输入格式:
输入为一组用空格间隔的整数,个数不超过100个,表示带空指针信息的二叉树先根序列。其中空指针信息用0表示
输出格式:
输入为一组整数,每个整数后一个空格,表示该树的层次遍历序列。
输入样例:
1 2 0 3 0 4 0 0 0
输出样例:
1 2 3 4
#include<bits/stdc++.h>
using namespace std;
int a[101];
vector<vector<int>> v(105);
void creat(){
int i=0;
stack<int >s;
s.push(a[i++]);
while(!s.empty()){
if(a[i])s.push(a[i++]);//如果a[i]不为空,继续遍历
else{
int l=s.size();
int t=s.top();
s.pop();
i++;
v[l].push_back(t);
}
}
return ;//
}
int main(){
int c=0,y;
while(cin>>y){
if(y=='\n')break;
a[c++]=y;
}
creat();
for(int i=0;i<v.size();i++){
for(int j=0;j<v[i].size();j++){
cout<<v[i][j]<<' ';
}
}
return 0;
}
列出叶结点
对于给定的二叉树,本题要求你按从上到下、从左到右的顺序输出其所有叶结点。
输入格式:
首先第一行给出一个正整数 N(≤10),为树中结点总数。树中的结点从 0 到 N−1 编号。随后 N 行,每行给出一个对应结点左右孩子的编号。如果某个孩子不存在,则在对应位置给出 "-"。编号间以 1 个空格分隔。
输出格式:
在一行中按规定顺序输出叶结点的编号。编号间以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6
输出样例:
4 1 5
#include<bits/stdc++.h>
using namespace std;
struct node{
int lchild,rchild;
}a[15];
int main(){
queue<int>q;
int n;
int check[15]={0},i,s[15],j=0;
cin>>n;
for(i=0;i<n;i++){
char l,r;
cin>>l>>r;
a[i].lchild=l!='-'?l-'0':12;
a[i].rchild=r!='-'?r-'0':12;
check[a[i].lchild]=1;
check[a[i].rchild]=1;
}
//寻找根节点,只有根节点不是谁的左右节点,输入的数据没有根节点的值
for(i=0;i<n;i++){
if(!check[i])break;
}
q.push(i);
while(!q.empty()){
int d=q.front();
q.pop();
if(d==12)continue;
if(a[d].lchild==12&&a[d].rchild==12)
s[j++]=d;
q.push(a[d].lchild);
q.push(a[d].rchild);
}
cout<<s[0];
for(i=1;i<j;i++){
cout<<' '<<s[i];
}
return 0;
}
朋友圈
某学校有N个学生,形成M个俱乐部。每个俱乐部里的学生有着一定相似的兴趣爱好,形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出,如果A和B是朋友,且B和C是朋友,则A和C也是朋友。请编写程序计算最大朋友圈中有多少人。
输入格式:
输入的第一行包含两个正整数N(≤30000)和M(≤1000),分别代表学校的学生总数和俱乐部的个数。后面的M行每行按以下格式给出1个俱乐部的信息,其中学生从1~N编号:
第i个俱乐部的人数Mi(空格)学生1(空格)学生2 … 学生Mi
输出格式:
输出给出一个整数,表示在最大朋友圈中有多少人。
输入样例:
7 4
3 1 2 3
2 1 4
3 5 6 7
1 6
输出样例:
4
#include<stdio.h>
//#include<math.h>
int f[30001],n,m;
int fu(int x){
if(x==f[x])return x;
return f[x]=fu(f[x]);
}
int main(){
int z[30001],i,k,x1,x2;
scanf("%d %d",&n,&m);
for(i=1;i<=n;i++){
f[i]=i;
z[i]=1;
}
while(m--){
scanf("%d %d",&k,&x1);
for(i=1;i<k;i++){
scanf("%d",&x2);
int l1=fu(x1);
int l2=fu(x2);
if(l1!=l2){//
f[l1]=f[l2];
z[l2]+=z[l1];
}
x1=x2;
}
}
int max=0;
for(i=1;i<=n;i++){
if(max<z[i])
max=z[i];
}
printf("%d",max);
return 0;
}
部落
在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。
输入格式:
输入在第一行给出一个正整数N(≤104),是已知小圈子的个数。随后N行,每行按下列格式给出一个小圈子里的人:
K P[1] P[2] ⋯ P[K]
其中K是小圈子里的人数,P[i](i=1,⋯,K)是小圈子里每个人的编号。这里所有人的编号从1开始连续编号,最大编号不会超过104。
之后一行给出一个非负整数Q(≤104),是查询次数。随后Q行,每行给出一对被查询的人的编号。
输出格式:
首先在一行中输出这个社区的总人数、以及互不相交的部落的个数。随后对每一次查询,如果他们属于同一个部落,则在一行中输出Y
,否则输出N
。
输入样例:
4
3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
2
10 5
3 7
输出样例:
10 2
Y
N
#include<bits/stdc++.h>
using namespace std;
int f[10005];//!数组的空间!
int fu(int x){
if(x==f[x])return x;
return f[x]=fu(f[x]);
}
int main(){
int n,i,k,t=0,c=0,x1,x2,l1,l2,q;
stack<int >s;
cin>>n;
while(n--){
scanf("%d %d",&k,&x1);
if(f[x1]==0){
t++;
f[x1]=x1;
s.push(x1);
}
for(i=1;i<k;i++){
scanf("%d",&x2);
if(f[x2]==0){
t++;
f[x2]=x2;
s.push(x2);
}
f[fu(x1)]=f[fu(x2)];
}
}
while(s.size()){//任选其一
//for(i=0;i<t;i++){
int d=s.top();
if(d==f[d])c++;
s.pop();
}
printf("%d %d\n",t,c);
scanf("%d",&q);
while(q--){
cin>>l1>>l2;
if(fu(l1)==fu(l2))
printf("Y\n");
else{
printf("N\n");
}
}
return 0;
}
修理牧场
农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li的总和。
但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。
请编写程序帮助农夫计算将木头锯成N块的最少花费。
输入格式:
输入首先给出正整数N(≤104),表示要将木头锯成N块。第二行给出N个正整数(≤50),表示每段木块的长度。
输出格式:
输出一个整数,即将木头锯成N块的最少花费。
输入样例:
8
4 5 1 2 1 3 1 1
输出样例:
49
#include<stdio.h>
#define o 10000000
int n,a[10001];
int findmin(){
int i,min=o;
for(i=0;i<n;i++){
if(min>a[i])
min=a[i];
}
return min;
}
void delete(int x){
int i;
for(i=0;i<n;i++){
if(a[i]==x){
a[i]=o;
break;
}
}
}
void add(int x){
int i;
for(i=0;i<n;i++){
if(a[i]==o){
a[i]=x;
break;
}
}
}
int main(){
int i,sum=0;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(i=0;i<n-1;i++){
int x1=findmin();
delete(x1);
int x2=findmin();
delete(x2);
sum+=x1+x2;
add(x1+x2);
}
printf("%d",sum);
return 0;
}
哈夫曼树
哈夫曼树,第一行输入一个数n,表示叶结点的个数。
需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出哈夫曼树的带权路径长度(WPL)。
输入格式:
第一行输入一个数n,第二行输入n个叶结点(叶结点权值不超过1000,2<=n<=1000)。
输出格式:
在一行中输出WPL值。
输入样例:
5
1 2 2 5 9
输出样例:
37
#include<stdio.h>
#define o 10000000
int n,a[10001];
int findmin(){
int i,min=o;
for(i=0;i<n;i++){
if(min>a[i])
min=a[i];
}
return min;
}
void delete(int x){
int i;
for(i=0;i<n;i++){
if(a[i]==x){
a[i]=o;
break;
}
}
}
void add(int x){
int i;
for(i=0;i<n;i++){
if(a[i]==o){
a[i]=x;
break;
}
}
}
int main(){
int i,sum=0;
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&a[i]);
}
for(i=0;i<n-1;i++){
int x1=findmin();
delete(x1);
int x2=findmin();
delete(x2);
sum+=x1+x2;
add(x1+x2);
}
printf("%d",sum);
return 0;
}
以上作为笔记使用