【算法分析】
设树中结点类型,包含char类型的val成员变量,意为结点的类型,可以是’F’, ‘B’或’I’。
估算该问题可能用到的最大结点数。易知FBI树是满二叉树,FBI串最长有2^N,N最大是10,也就是说这个树的叶子结点最多有 2^10个,整棵树的结点数为 2^0+2^1+...+2^10==2^11-1=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’。
得到树后,对这棵树做后序遍历。
【参考代码】
#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)
{
if(fs[0]=='1')
node[np].val='I';
else
node[np].val='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;
}
`substr()`是C++中`std::string`类的一个成员函数,用于从字符串中提取子串。其基本语法是`string.substr(pos, len)`,其中`pos`是子串的起始位置,`len`是要提取的子串的长度。
详细解释如下:
- `pos`(起始位置):这是一个必选参数,表示子串的起始位置。位置从0开始计数。如果`pos`等于字符串的长度,则返回一个空字符串;如果`pos`大于字符串长度,则抛出`out_of_range`异常。
- `len`(长度):这是一个可选参数,表示要提取的子串的长度。如果省略此参数或设置为`string::npos`,则提取从`pos`开始直到字符串末尾的所有字符。
函数返回一个新的字符串对象,包含指定的子串。