【问题描述】
我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串。
FBI树是一种二叉树,它的结点类型也包括F结点,B结点和I结点三种。由一个长度为2N的“01”串S可以构造出一棵FBI树T,递归的构造方法如下:
(1)T的根结点为R,其类型与串S的类型相同;
(2)若串S的长度大于1,将串S从中间分开,分为等长的左右子串S1和S2;由左子串S1构造R的左子树T1,由右子串S2构造R的右子树T2。
现在给定一个长度为2N的“01”串,请用上述构造方法构造出一棵FBI树,并输出它的后序遍历序列。
【输入文件】
输入文件fbi.in的第一行是一个整数N(0<=N<=10),第二行是一个长度为2N的“01”串。
【输出文件】
输出文件fbi.out包括一行,这一行只包含一个字符串,即FBI树的后序遍历序列。
【样例输入】
3
10001011
【样例输出】
IBFBBBFIBFIIIFF
【数据规模】
对于40%的数据,N <= 2;
对于全部的数据,N <= 10。
构建二叉树
从上至下,存储当前整棵树的根节点类型,再从中切断递归生成各个左右子树根节点类型,递归边界是二分到当前子树为空
#include using namespace std;
int a[20] = {0,1,0,0,0,1,0,1,1};
int s[20] = {0,1,1,1,1,2,2,3,4};//用于判断某一范围内是哪种节点,在循环的基础上做了一点优化,s[3] - s[1]就能判断3到2范围内是什么值。
struct node{
char data;
node *l,*r;
};
void create(node *t,int st,int ed)
{
int sum = s[ed]-s[st-1];
if(sum == 0)t->data = 'B';
else if(sum == ed-st+1)t->data = 'I';
else t->data = 'F';
if(st==ed)return ;
node *L,*R;
R = new node;
L = new node;
R->l = NULL;R->r = NULL;
L->l = NULL;L->r = NULL;
t->l = L;t->r = R;
create(t->l,st,(st+ed)/2);
create(t->r,(st+ed)/2+1,ed);
}
void print(node *p)
{
if(p==NULL)return;
print(p->l);
print(p->r);
cout << p->data;
}
int main()
{
node *root;
root = new node;
root->l = NULL;
root->r = NULL;
create(root,1,8);
print(root);
}
顺序存储二叉树
从下至上依次生成节点,直到根节点
//if(node[k*2]=='B' && node[k*2+1]=='I'|| node[k*2]=='I' && node[k*2+1]=='B'|| node[k*2]=='F' || node[k*2+1]=='F')
#includeusing namespace std;
int n,m=1;
char node[10000000];
void houxu(int k)
{
if(k>=2*m) return;
houxu(k*2);
houxu(k*2+1);
cout << node[k];
}
int main()
{
char ch;
cin>>n;
for(int i=1;i<=n;i++)m*=2;
for(int i=m;i<=2*m-1;i++)
{
cin>>ch;
if(ch=='0')
{
node[i]='B';
}else
{
node[i]='I';
}
}
for(int i = 1; i<2*m; i++)
cout << node[i] <0;k--)
{
//if(node[k*2]=='B' && node[k*2+1]=='I'|| node[k*2]=='I' && node[k*2+1]=='B'|| node[k*2]=='F' || node[k*2+1]=='F')
if(node[k*2]=='B'&&node[k*2+1]=='B')
{
node[k]='B';
}else if(node[k*2]=='I'&&node[k*2+1]=='I')
{
node[k]='I';
}
else node[k] = 'F';
}
houxu(1);
}