我正在以广度优先的方式实现数组表示中的动态 kD-Tree (以std :: vector存储节点)。每个i
个非叶子节点在(i<<1)+1
处有一个左子节点,在(i<<1)+2
处有一个右子节点。它将支持逐点插入点和集合点。
但是,我正面临着确定增量预分配空间所需的可能节点数的问题。
我找到了formula on the web,这似乎是错误的:
N = min(m - 1,2n - ½m - 1),
其中m是大于或等于n的2的最小幂,即 点数。
我对公式的实施如下:
size_t required(size_t n)
{
size_t m = nextPowerOf2(n);
return min(m - 1, (n<<1) - (m>>1) - 1);
}
function nextPowerOf2返回2的最大或等于n的幂
任何帮助都将不胜感激。
答案 0 :(得分:1)
kd树的每个节点将空间划分为两个空格。因此,kd树中的节点数取决于您执行此划分的方式:
1)如果你在空间的中点划分它们(也就是说,如果空间是从x1到x2,你用x3 =(x1 + x2)/ 2行划分空间),然后: i)每个点都将分配自己的节点,和 ii)每个中间节点都是空的。
在这种情况下,节点数将取决于点的坐标有多大。如果坐标以| X |为界,则kd-tree中的节点总数应略小于log | X |。 * n(更确切地说,在最差的情况下,在log | X | * n - n log n + 2n附近)。要看到这一点,请考虑以下添加点的方法:添加多个集合,每个集合有两个非常接近的点。对于每对点,树将需要连续划分空间log | X |次,如果是log | X |显着大于log n,创建log | X |过程中的中间节点。
2)如果使用点作为分界线来划分它们,则每个节点(包括中间节点)将包含一个点。因此,节点的总数简单地为n。但是,请注意,如果不以随机顺序给出点,则使用点来划分空间可能会产生非常糟糕的性能(例如,如果点以X的升序给出,则树的深度会为O(n)。为了比较,(1)中树的深度最多为O(log | X |))。