Vijos1114解题报告(不建树解决二叉树问题)
来源:互联网 发布:excel 重复数据统计 编辑:程序博客网 时间:2024/05/16 10:25
我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串。
FBI树是一种二叉树1,它的结点类型也包括F结点,B结点和I结点三种。由一个长度为2^N的“01”串S可以构造出一棵FBI树T,递归的构造方法如下:
1) T的根结点为R,其类型与串S的类型相同;
2) 若串S的长度大于1,将串S从中间分开,分为等长的左右子串S1和S2;由左子串S1构造R的左子树T1,由右子串S2构造R的右子树T2。
现在给定一个长度为2^N的“01”串,请用上述构造方法构造出一棵FBI树,并输出它的后序遍历2序列。
解题思路:使用函数求出每个节点,然后通过该节点构建树,最后遍历树即可。
难点:建树函数void buildtree(int start, int end, treeNode* &root) 当start与end相等时,如果递归参数不当,如构建左子树使用函数buildtree(start, (start+end)/2, root->lc),会陷入无限递归的深渊。
处理方法:
1:求串的左半边时用(start+end+1)/2-1;求右半边用(start+end)/2+1, 构建函数最开始用判断条件start>end时return;
2: 构建函数在递归调用前判断start是否等于end如果等于不递归调用函数;
代码:
#include <cstdio>#include <cstring>#include <cmath>const int MAXN = 2000;char str[MAXN];int nodenum;class treeNode{ public: treeNode *lc; treeNode *rc; char c;};char findRoot(int start, int en){ if(start > en) return 'N'; int i; char first = str[start]; for(i=start; i <= en; i++) { if(str[i] != first) return 'F'; } if(first == '0') return 'B'; return 'I';}void buildtree(int start, int end, treeNode* &root){ if(start > end) { root = NULL; return; } char rootc; rootc = findRoot(start, end); root = new treeNode; root->c = rootc; buildtree(start,(start + end + 1) / 2-1, root->lc); buildtree((start + end) / 2+1, end, root->rc);}void lvisit(treeNode *root){ if(root == NULL) return; lvisit(root->lc); lvisit(root->rc); printf("%c", root->c);}int main(){ scanf("%d", &nodenum); scanf(" %s", str); nodenum = pow(2, nodenum); treeNode *root = NULL; buildtree(0, nodenum-1, root); lvisit(root); printf("\n");}
优化:
上面的方法过于麻烦:
其实由于树是先序建立的,所以如果建立根结点后,递归建立左子树和右子树前就把节点的值输出,那么树建立结束的同时就输出树的先序遍历序列。如果在建立左右子树后再输出节点的值,那么最后输出了树后序遍历序列。如果在建立左子树后,建立右子树前输出节点的值,那么最后输出了树的后序遍历序列。
只要符合先序建树的条件就可以用这种方法。
这样以来就不用保存树的节点,也不用在遍历树了。减少了时间复杂度和空间复杂度。
代码如下:
使用处理方法1:
#include <cstdio>#include <cstring>#include <cmath>const int MAXN = 1050;char str[MAXN];int nodenum;char findRoot(int start, int en){ while(start<en) { if(str[start] != str[en]) return 'F'; start++; } if(str[en] == '0') return 'B'; return 'I';}void buildtree(int start, int end){ if(start > end) return; buildtree(start,(start + end + 1) / 2-1); buildtree((start + end) / 2+1, end); printf("%c", findRoot(start, end));}int main(){ scanf("%d", &nodenum); scanf(" %s", str); buildtree(0, pow(2, nodenum)-1); printf("\n");}
进一步优化:
在求每个节点时,其实不用重新遍历串了,只需根据该节点左右孩子就可以确定该节点是F还是B还是I。如果左右节点不同,该节点为F,否则该节点和其左右节点相同。这样时间复杂度会进一步降低,代码如下:
#include <cstdio>#include <cstring>#include <cmath>const int MAXN = 1025;char str[MAXN];int nodenum;char buildtree(int start, int end){ char a; if(start != end) { a = buildtree(start,(start + end)/2); if(a!= buildtree((start + end)/2+1, end)) a = 'F'; printf("%c", a); return a; } if(str[start] == '0') a = 'B'; else a = 'I'; printf("%c", a); return a;}int main(){ scanf("%d", &nodenum); scanf(" %s", str); buildtree(0, pow(2, nodenum)-1); printf("\n");}
- Vijos1114解题报告(不建树解决二叉树问题)
- 二叉树——不建树遍历
- BST 二叉搜索树 (动态建树与静态建树)
- UVA 548Tree(二叉树建树)
- 二叉树层次建树.
- 二叉树建树
- 二叉树建树
- vijos1114
- NOI 1192 加分二叉树 解题报告
- 百练-2756-二叉树-解题报告
- 九度1113:二叉树 解题报告
- 蓝桥杯 横向二叉树 解题报告
- 【剑指Offer】重建二叉树 解题报告
- 二叉树的子树 解题报告
- 二叉树非递归建树
- 二叉树的建树方法
- 数据结构——二叉树的建立和遍历(递归建树&层序遍历建树)
- HDU4521解题报告(DP解决)
- 黑马程序员——java基础学习笔记——第十一天
- Light OJ 1238--BFS(第一道自己做的)
- EJB到底是什么,真的那么神秘吗??
- 广州酷狗php面试题(赋答案)
- 第四周项目一:三角形类的构造函数(4)
- Vijos1114解题报告(不建树解决二叉树问题)
- 第三周项目五——数组做数据成员(1)
- 第四周 阅读程序 4
- HaahTable 再Hash
- Web_JavaScript_JS函数模块库;
- hdu4400 STL应用 查找思维题
- 个人作业
- 【SICP练习】142 练习3.77
- 更改IntelliJ的快捷键为Eclipse风格,并且恢复Alt+/代码自动补全快捷键code completion