信息学奥赛一本通 1365:FBI树(fbi) | 1928:【04NOIP普及组】FBI树 | 洛谷 P1087 [NOIP2004 普及组] FBI 树

【题目链接】

ybt 1365:FBI树(fbi)
ybt 1928:【04NOIP普及组】FBI树
洛谷 P1087 [NOIP2004 普及组] FBI 树

【题目考点】

1. 二叉树

【解题思路】

设树中结点类型,包含char类型的val成员变量,意为结点的类型,可以是’F’, ‘B’或’I’。
估算该问题可能用到的最大结点数。易知FBI树是满二叉树,FBI串最长有 2 N 2^N 2N,N最大是10,也就是说这个树的叶子结点最多有 2 10 2^{10} 210 个,整棵树的结点数为 2 0 + 2 1 + . . . + 2 10 = 1 ( 1 − 2 11 ) 1 − 2 = 2 11 − 1 = 2047 2^0+2^1+...+2^{10}=\frac{1(1-2^{11})}{1-2}=2^{11}-1=2047 20+21+...+210=121(1211)=2111=2047,数组长度设为2050刚刚好。
设函数createTree,参数为fs。意为:根据FBI串fs来构建一棵二叉树。
FBI串的长度都是2的整数幂,下表从0开始,长度为fs.length()。那么fs.length()/2为中间偏右的位置。左半边下标范围为0~fs.length()/2-1,右半边下标范围为fs.length()/2~fs.length()-1。取子串得到左右子树的FBI串,递归调用本函数根据FBI串生成左右子树。

  • 若左右子树根结点的类型相同,那么这棵树根结点也是这个类型(左右子树根结点的类型如果都是I,那么根结点类型也为’I’;若都是’B’, 根结点类型为’B’)。
  • 若左右子树根结点的类型不同,那么这棵树根结点的类型为’F’。

递归出口为:如果FBI串fs长度为1,那么这个结点是叶子结点。看这个字符串中的唯一的字符来确定这个结点的val。

  • 如果是’1’,那么这个叶子结点的val为’I’。
  • 如果是’0’, 那么这个叶子结点的val为’B’。

得到树后,对这棵树做后序遍历。

【题解代码】

解法1:使用string类

#include <bits/stdc++.h>
using namespace std;
#define N 2050
struct Node
{
    
    
	char val;//结点类型,可以是'F', 'B', 或'I' 
	int left, right;
};
Node node[N];//结点池 
int n, p;
string s;
int createTree(string fs)//根据FBI串fs构建二叉树,返回二叉树的根 
{
    
    
	int np = ++p;
	if(fs.length() == 1)
	{
    
    
		node[np].val = fs[0] == '1' ? 'I' : 'B';
		return np;	
	}
	string ls = fs.substr(0, fs.length()/2), rs = fs.substr(fs.length()/2);
	int lp = createTree(ls), rp = createTree(rs);
	node[np].left = lp, node[np].right = rp;
	if(node[lp].val == node[rp].val)
		node[np].val = node[lp].val;//如果二者相同,那么父节点 
	else
		node[np].val = 'F';
	return np;
}
void postOrder(int r)
{
    
    
	if(r == 0)
		return;
	postOrder(node[r].left);
	postOrder(node[r].right);
	cout << node[r].val;
}
int main()
{
    
    
	cin >> n >> s;
	int root = createTree(s);
	postOrder(root);
	return 0;
}

解法2:使用字符数组

#include <bits/stdc++.h>
using namespace std;
#define N 2050
struct Node
{
    
    
	char val;
	int left, right;
};
Node node[N];
int p;
char s[N];
int createTree(int l, int r)//通过s[l]~s[r]的字符串建立FBI树,返回树根结点的地址 
{
    
    
	int np = ++p;
	if(l == r)
	{
    
    
		if(s[l] == '0')
			node[np].val = 'B';
		else
			node[np].val = 'I';
		return np;
	}
	int lp = createTree(l, (l+r)/2), rp = createTree((l+r+1)/2, r);//(l+r+1)/2是中间偏右位置 
	node[np].left = lp, node[np].right = rp; 
	if(node[lp].val == node[rp].val)
		node[np].val = node[lp].val;
	else
		node[np].val = 'F';
	return np;
}
void postOrder(int r)
{
    
    
    if(r == 0)
    	return;
    postOrder(node[r].left);
    postOrder(node[r].right);
    cout<<node[r].val;
}
int main()
{
    
    
	int n, n1;
    cin >> n1;
    n = (int)pow(2,n1);//n:字符串总长度 
    cin >> s;
    int root = createTree(0, n-1);
    postOrder(root);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/lq1990717/article/details/127431342