如何有效地修剪和合并四叉树中的节点?

How can I efficiently prune and merge nodes in a quadtree?

本文关键字:节点 四叉树 合并 有效地 修剪      更新时间:2023-10-16

我正在使用四叉树来有效地收集某个2D区域中的粒子。粒子会随着时间的推移而褪色并最终消失,所以我需要在它们死亡时将它们从四叉树中移除。

我面临的问题是,如何最好地修剪四叉树以删除空节点,并在节点不再有足够的粒子来证明拆分的合理性时合并节点。

我的第一个想法是递归遍历树,检查每个子节点。如果所有 4 个节点都是空的,那么我会用一个标志将其传递到调用堆栈(true 表示空,如果不是,则为 false(,否则,我将检查每个子节点中的粒子数量,如果它们都小于MAX_PER_NODE,则将所有粒子拉入父节点并删除子节点。

也许像下面这样(在我写这篇文章时,这个伪代码实际上是意识流,所以对它持保留态度(:

class QuadTreeNode
{
public bool prune();
public void deleteChildren(); //just assume it does what you expect...
private:
std::vector<ParticleType> particles;
std::vector<QuadTreeNode*> children; // size <= 4
};
bool QuadTreeNode::prune()
{
bool allChildrenEmpty = true;
for(QuadTreeNode & n : children)
{
allChildrenEmpty &= n.prune();
}
//Merging could be handled by returning the number of particles instead of true/false
//If the total number of particles falls below the max per bucket, pull the particles into the
//current node and delete the children...
if(allChildrenEmpty) this.deleteChildren();
return allChildrenEmpty && (!this.particles.size());    
}

然而,这似乎是低效的,因为我觉得这需要我触摸树中的每个节点(尽管我想这比访问每个粒子要好(。

有没有更好的方法来实现这种修剪和合并操作?

假设您没有受到严重的 RAM 约束,您可以为每个节点添加一个权重计数器,表示其本身的粒子总数及其十进制。 每当你插入或删除一个粒子时,你都会更新它,这实际上并不昂贵,因为你无论如何都要将这些节点拉到L1中。

然后,当您删除时,您还可以检查重量是否