当一棵nvc tree不断的加入名字,tree就会变得越来越大。比如我们要建一棵在一个国家下面直接找一条道路这个功能的tree。这时候的做法,就把这个tree切分成多个subtree,每个subtree可以控制在我们可以接受的大小范围内。这就引出来一个问题,如果切分出subtree?
什么样的subtree是好的切分方法,由平均主义我们可以认为,各个subtree的大小应该一致,尽量差不多,不要一个有1m,另一个大小只有10k。
自己尝试了2中subtree的切分方法,基本上效果还好,但是很多情况下,各个subtree的size之间还是差异比较大,特别是有些节点下面挂了很多分支,每个分支都很小,但是 当前节点作为subtree又很大,特别是中文的情况下,在道路nvc中,一个汉字下面可能接3000多个汉字。
方法一,设定4000个节点为标准,从tree中找出一个节点,这个节点下面的子孙节点个数为大于4000中最小的一个。具体做法:
1,通过递归,把tree中每个节点记录下本节点包含的子孙节点的个数。
2,遍历一遍tree中的节点,把1中记录的个数中,大于等于4000,同时是最小的节点找到。
3,把这个节点当成subtree的root,把其中tree中切分出来。
4,重复1开始下一次查找,直到找到的节点就是tree本身的root节点。
这个方法总是越到后面,找到的subtree大小越不一致。改进成方法二
方法二,把大于4000中最小的节点,改成与4000的差值最小的节点。
1,通过递归,把tree中每个节点记录下本节点包含的子孙节点的个数。
2,遍历一遍tree中的节点,把1中记录的个数,计算与4000的差值,差值最小的节点找到。
3,把这个节点当成subtree的root,把其中tree中切分出来。
4,重复1开始下一次查找,直到找到的节点就是tree本身的root节点。
改进后,找到的subtree平均很多了,不过还是有比较大的差异。这是目前本人使用的方法。
不晓得有没有其他实现简单的方法。
新的思考:
上面的方法在划分subtree的时候,共同父的子节点总是分在同一个subtree中,这导致了subtree的划分不可能达到非常平均负载。特别是中文情况,汉字的下一个汉字几百上千种情况完全可能。为了更平均的负载,应该允许共同父的子节点可以分配在不同的subtree,这样可以按需要,当部分子节点刚好填满subtree的容量,划分停止,启动一个新的subtree来包含剩下的子节点。
同父的子节点划到一颗subtree上,好处是在当前的subtree上就可以做到完备的逻辑判断。如果把子节点分配到了2个不同subtree,这样我们需要同时对2个subtree进行逻辑判断,然后对结果进行合并去重,这样必然带来了代码的复杂性。同时,代码在解析nvctree的时候,应该能够透明处理这2种不同的划分方法,这个就需要好好设计下subtree的解析代码。