#include using namespace std; //需要开大一点,否则RE,得了90分。 const int N = 1e5 + 10; /** 以1011为例 1011 10 11 1 0 1 1 F(7) F(3) I(6) I(1) B(2) I(4) I(5) 后序:IBFIIIF(遍历顺序已标注) (编号为二叉树深度) 1.比如1011,很明显是F 2.然后先不输出,先遍历左子树10(F) 3.还是不输出先遍历左子树1(I) 3.发现不能再分(长度为1时停止)输出 I 2.回到10 继续遍历右子树0(B) 3.发现不能再分,输出B 2.回到10, 所有子树遍历完毕,于是输出F 1.回到1011,遍历右子树11(I) 2.先不输出,继续遍历左子树1(I) 3.发现不能再分,输出I 2.回到11, 遍历右子树1(I) 3.发现不能再分,输出I 2.回到11,子树全部遍历完毕,于是输出I 1.回到1011,输出F */ //树的结构体+存储数组 struct Node { int id; //id编号 int left; //左结点 int right; //右结点 char value; //当前结点的value值 } t[N]; int n, m; string s; //2^n长度的01串 /** * 功能:获取字符串s的类型 * @param s * @return */ char getStype(string s) { int zeroCnt = 0, oneCnt = 0; for (int i = 0; i < s.length(); i++) if (s[i] == '1') oneCnt++; else zeroCnt++; if (oneCnt == 0)return 'B'; else if (zeroCnt == 0) return 'I'; return 'F'; } /** * 功能:构建FBI树 * @param start 开始的位置 * @param end 结束的位置 */ void build(string s, int pos) { /** 递归的构造方法如下: T的根结点为R,其类型与串S的类型相同; 若串S的长度大于1,将串S从中间分开,分为等长的左右子串S_1和S_2 由左子串S_1构造R的左子树T_1,由右子串S_2构造R的右子树T_2 */ char v = getStype(s); t[pos].id = pos; t[pos].value = v; if (s.length() > 1) { t[pos].left = 2 * pos; t[pos].right = 2 * pos + 1; //左树 build(s.substr(0, s.length() / 2), t[pos].left); //右树 build(s.substr(s.length() / 2), t[pos].right); } } //利用递归进行后序遍历 void post_order(Node node) { if (node.id) { post_order(t[node.left]); post_order(t[node.right]); cout << node.value; } } int main() { //这个n是无用的,因为是上古的考题,都是C时代的,要求使用char数组,没有n说不过去,现在都用string了,不需要n了。 cin >> n >> s; //利用递归构建FBI树 build(s, 1); //进行后序遍历 post_order(t[1]); return 0; }