今天终于有空来说说4叉树的相邻节点。上次在2D场景导航中提起,但一直没有详细讨论.经过我仔细研究,最终得到了较快的一个解决方案。方案的核心在于对节点的编码上。
编码
由于是四叉树,即每个节点有四个子节点,很自然会想到使用2位四进制编码。 如图:(1) 。这样编码的原因是: 使用低位代表y,使用高位代表x,从而可以得到将一个编码转换到二维坐标中,并有利于计算。
显然,一颗树不会只有一层,那么我们是不是可以将层信息也存储到编码中呢?设树最大16层,则需要4位二进制编码来保存层信息。再进一步,能不能在编码中将父节点的信息也存储下来呢?在一定程度上讲是可以的,只在最大层数不太多。
可以使用从低到高位进行编码,每两位表示一个节点,那么一个32位的DWORD可以保存16个节点数据(将层数据单独保存)比如使用0001可以表示图中完整的信息
(2)
我们可以定义一个结构
struct TreeNodeID{
int level;
int id;
}
计算
1,计算邻节点
有了这个编码后,邻节点计算就很简单了。还是拿0001这个红色的节点来说吧。我们来计算他的左右两个节点。
左节点,将x-1。0001中两个0分别表示是了节点的x坐标和节点的父节点的x坐标,都为0。我们将这两个x坐标提取出来。得到"00”,00-1 = 11,同时在高位产生一个借位,0000-0011=1111,有下划线的两位1就是通过借位产生的。 然后再将x与y合成。得到11011,由于只有两层,显示这个数字溢出了,它大于了16,因此我们可以判定左节点为空。
右节点,将x+1。同样,提取0001中的两个0,放到一个变量x中,x=00。提取y=01。将x+1,得x=01。再将x与y合成为一个ID:0011。0011这个节点即0001的右节点。
2,判断ID是否溢出.
if( id>=(1<<(level<<1)) ) 溢出 else 没有溢出。
3,如何快速的提取编码中的x,y信息进行运算。
我们提取x,y只是为了算术运算,所以,如果是向左,执行x-1操作时可以将0001中的y位都置0,0001 & 1010 = 0000,即x=0x0,x-1 = 0xffffffff,变成了全1。将x中的y位清0,再与原来的y合成就得到了111011(高位都是1,没有列出)。
结束
说了这么多,不知道说清楚了没 ;) 我在这里也只是抛砖引玉,希望您有更好的算法可以拿出来交流。