我正在尝试使用KD树平衡一组(百万+)3D点,我有两种方法。
方式1:
使用O(n)算法查找给定轴上的arraysize / 2nd最大元素并将其存储在当前节点
迭代向量中的所有元素,并将它们与我刚刚找到的元素进行比较,并将它们放在newArray1中,将那些较小的元素放在newArray2中
递归
方式2:
使用quicksort O(nlogn)沿给定轴对数组中的所有元素进行排序,取位于arraysize / 2的元素并将其存储在当前节点中。
然后将newArray1中索引0到arrayize / 2-1的所有元素,newArray2中的arraysize / 2和arraysize-1中的所有元素
递归
我该怎么办?或者有更好的方法来做到这一点,我甚至没有看到?
答案 0 :(得分:2)
方式3:
使用诸如QuickSelect之类的O(n)算法来确保位置长度/ 2处的元素是正确的元素,之前的所有元素都是较少的,之后的所有元素都比它大(不完全排序! ) - 这可能是你在你的方法1步骤1中使用的算法......
递归到每一半(中间元素除外)并重复下一个轴。
请注意,您实际上不需要创建“节点”对象。实际上,您可以将树保存在一个大型数组中。搜索时,使用第一个轴从长度/ 2开始。
我已经看到ELKI正在使用这个技巧。它使用非常少的内存和代码,这使得树非常快。
答案 1 :(得分:0)
另一种方式:
为每个维度排序:O(K N log N)。这将只执行一次,我们将利用维度上的排序列表。
对于当前维度,找到O(1)时间的中位数,在O(N)时间内拆分中位数,在O(KN)时间内拆分每个维度的排序数组,并递归下一个维度。
通过这种方式,您将在开始时执行排序。并针对已知值对每个子树执行(K + 1)分割/过滤。对于小K,这种方法应该比其他方法更快。
注意:Anony-Mousse指出的技巧可以减少算法所需的额外空间。
答案 2 :(得分:0)
请注意,如果查询超矩形包含许多点(例如,所有这些点),那么树是否平衡无关紧要。如果查询超级域很小,则平衡树很有用。