洛谷p1087 FBI树题解——法一、链式存储(指针)建树,遍历;法二、递归,不建树

【传送门】https://www.luogu.org/problemnew/show/P1087

【题解】本题主要考察树的遍历,要求对递归有深刻的理解。

1、建树。按照题意,建树的过程实际上是先序遍历,即先根,再左子树、右子树。当字符串长度为1时,读入根结点值后令左、右指针为NULL。当字符串长度大于1时,读入根结点值后再递归建立左、右子树。

2、判断。判断当前节点的FBI树类型,令int B=1,I=1,然后遍历当前节点,如果遇到'0',令I=0,表示有'0';如果遇到'1',令B=0,表示有'1'。如果B=1没有改变,说明全为'0';如果I=1没有改变,说明节点全为'1'。两个都有改变,则说明节点既有'0',又有'1'。

3、输出。输出过程是对树的后序遍历(先左、右子树,再根节点)。可以和建树过程集成在一起,也就是递归建立左子树、右子树退出后输出根结点值。但为了练习如何建树,如何输出遍历,下面题解没有这样做。

【AC代码1】孩子表示法,链式存储结构,指针建树

//lg p1087 FBI树  AC代码 通过此题学习用指针建树,孩子表示法 
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=(1<<10)+5;
int n=3;
char str[maxn]="10001011";
struct node{ //自引用结构。 
	char data;
	node *lt,*rt;
	/*
	“node *lt,*rt;”
	如果写成“node lt”,则属于非法,因为lt是另一个完整的结构,其内部还将包含它自己的成员lt,
	这第二个lt又是一个完整的结构,它还将包含自己的成员lt。
	但写成“node *lt;”,则合法,因为现在lt不是结构体,而是一个指针,编译器知道指针的长度。 
	*/
};
node *T;//申明一个指针,指向结构体node。在定义结构体时并不分配内存,只有定义了结构体变量时才分配,初始为NULL 
void make_tree(node *T,int l,int r){//*不能少,否则编辑错误。申明T是指向node的指针 	
	//判断根树是'F'或'B'或'I'
	int B=1,I=1;
	for(int i=l;i<=r;i++){
		if(str[i]=='1')B=0;
		else I=0;
	}
	if(B)T->data='B';//这里的T是指针,从而写成T->data。如果申明node U,则写成U.data。回到本行代码,也可以写成(*T).data。 
	else if(I)T->data='I';
	else  T->data='F';
	
	//递归建树 
	if(l<r){
		T->lt=new node;T->rt=new node; 
		make_tree(T->lt,l,(l+r)/2);
		make_tree(T->rt,(l+r)/2+1,r);
	}
	else{
		T->lt=new node;T->rt=new node;//这句话可以省略不写 
		T->lt=NULL;
		T->rt=NULL;
	} 
}
void print(node* T){ //*不能少,否则编辑错误。申明T是指针 
	if(T){
		print(T->lt);
		print(T->rt);
		printf("%c",T->data);
	}
}
int main(){
//	freopen("in.txt","r",stdin);
	scanf("%d%s",&n,str);
	T=new node;//要求先申请新内存才可以对T进行操作 
	//cout<<T<<endl;
	make_tree(T,0,(1<<n)-1); //1<<n-1先运算n-1,再左移。(1<<n)-1先运算左移,再减1 
	//cout<<T<<endl;
	print(T);
	return 0;
}

【AC代码2】递归,不建树

//lg p1087 FBI树  不建树的写法,用递归 
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=1<<10+5;
int n=3;
char str[maxn]="10001011";
void mk(int l,int r){	
	//判断根是'F'或'B'或'I'
	int B=1,I=1;
	for(int i=l;i<=r;i++){
		if(str[i]=='1')B=0;
		else I=0;
	}
	int c;
	if(B)c='B';
	else if(I)c='I';
	else  c='F';
	//递归 
	if(l<r){
		mk(l,(l+r)/2);//左 
		mk((l+r)/2+1,r);//右 
		printf("%c",c);//根 
	}
	else printf("%c",c);//根 
}

int main(){
	scanf("%d%s",&n,str);
	mk(0,(1<<n)-1); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36314344/article/details/81489799
今日推荐