Algorithm 如何有效地分割单元中的二维空间,使每个单元最多包含K个点?

Algorithm 如何有效地分割单元中的二维空间,使每个单元最多包含K个点?,algorithm,language-agnostic,data-structures,Algorithm,Language Agnostic,Data Structures,我有一个2D点的数据集(其中约500k点),我想对其执行某种样方计数分析。样方计数的基础是将二维空间分割成规则网格(每个单元都有大小SxS),并计算每个单元中的点数 出于某种原因,我想做一点小小的改变:我不想使用常规网格,而是希望构建网格,使每个单元格最多包含K点 我所做的是:我从整个空间开始,将它分成4个单元(通过将每个维度“切割”成两半)。然后,我计算每个单元格中的点数。对于那些包含超过K个点的点,我会再次将它们分开,以此类推,直到完成为止 我尝试了这个简单算法的递归和迭代实现,但在应用于整

我有一个2D点的数据集(其中约500k点),我想对其执行某种样方计数分析。样方计数的基础是将二维空间分割成规则网格(每个单元都有大小
SxS
),并计算每个单元中的点数

出于某种原因,我想做一点小小的改变:我不想使用常规网格,而是希望构建网格,使每个单元格最多包含
K

我所做的是:我从整个空间开始,将它分成4个单元(通过将每个维度“切割”成两半)。然后,我计算每个单元格中的点数。对于那些包含超过
K
个点的点,我会再次将它们分开,以此类推,直到完成为止

我尝试了这个简单算法的递归和迭代实现,但在应用于整个数据集时,没有一个算法表现良好。很明显,主要的瓶颈是计数部分,所以我想知道什么样的数据结构可以让我高效地完成这项工作


(目前,我只是在Python中使用“条件索引”:
points=points[points[,1]>x1和points[,1]y1和points[,2]这还不完整,但它可能为您指明了正确的方向

不要从大的开始变小,而是从小的开始变大

将您的空间划分为100x100个单元格。计算每个单元格中的数字(这正好是O(n),每个单元格计算一次。)

从那时起,你不需要计算细胞数,你可以创建细胞组来计算它拥有的细胞数,然后我会使用一种算法将细胞组合成细胞组

可以考虑采用两个小单元来合并并重新计算的方法。

while(true) {
    take the smallest cellgroup
    compare it to each other cellgroup starting with the second smallest
    go up the list until you find two adjecent cell groups
    if you find a match
        merge them
        update the cellgroup size rankings
        repeat the process (continue the while(true)
    otherwise
        break out, you're done merging cells

}

这还不完整,但它可能会为您指明正确的方向

不要从大的开始变小,而是从小的开始变大

将您的空间划分为100x100个单元格。计算每个单元格中的数字(这正好是O(n),每个单元格计算一次。)

从那时起,你不需要计算细胞数,你可以创建细胞组来计算它拥有的细胞数,然后我会使用一种算法将细胞组合成细胞组

可以考虑采用两个小单元来合并并重新计算的方法。

while(true) {
    take the smallest cellgroup
    compare it to each other cellgroup starting with the second smallest
    go up the list until you find two adjecent cell groups
    if you find a match
        merge them
        update the cellgroup size rankings
        repeat the process (continue the while(true)
    otherwise
        break out, you're done merging cells

}

我对Python不太熟悉,但如果您针对每个象限运行整个数组,则可以对其进行改进:

在每次分割后,根据它们对应的象限对点进行分组。进一步分割象限时,只分析相应的子阵列。这可能会加快计数速度


你也可以考虑不规则网格,你可以考虑选择分离线,总是把潜水点分成相等的组(水平和垂直的分割应该分开进行)。

< P>我不太熟悉Python,但是如果你遍历每个象素的整个数组,它可以被改进:

在每次分割后,根据它们对应的象限对点进行分组。进一步分割象限时,只分析相应的子阵列。这可能会加快计数速度


此外,由于不规则网格,你可以考虑选择分离线,总是将潜水点分成相等的组(水平和垂直分开)。(因为如果点非常聚集,大单元的第一个“切割”将只包含一个包含所有点的“子单元”,而其他三个则没有)。另一方面,你描述的从小到大的方法将把所有空单元格与相邻单元格合并。换句话说,它将给出最小数量的单元格,使每个单元格最多有K个点。不过,我并不是说一种方法比另一种好。只是它们不一样。我不确定你的方法是否能理解我的意思尝试这样做(我必须考虑一下)。但您会继续合并单元格,直到达到无法进一步合并单元格的状态。这可能不是最理想的状态(即,可能会以不同的方式拆分单元格,从而生成较少的最终单元格组)但是这应该是一个相当不错的方法。对。因此,使用你的方法,你将不会有空单元格,并且大多数单元格至少有K/2个点。但是,使用我的方法,你最终会有空单元格,并且单元格只有很少的点。而且,没有任何东西表明你也不能将最大的单元格分成两组,将两者结合起来方法。好吧,结果将不一样。使用从大到小的技术,我将得到只有很少或根本没有数据点的单元(因为如果点非常聚集,大单元的第一个“切割”将最终只有一个包含所有点的“子单元”,而其他三个则没有)。另一方面,你描述的从小到大的方法将把所有空单元格与相邻单元格合并。换句话说,它将给出最小数量的单元格,使每个单元格最多有K个点。不过,我并不是说一种方法比另一种好。只是它们不一样。我不确定你的方法是否能理解我的意思尝试这样做(我必须考虑一下)。但您会继续合并单元格,直到达到无法进一步合并单元格的状态。这可能不是最理想的状态(即,可能会以不同的方式拆分单元格,从而生成较少的最终单元格组)但是这应该是一个相当不错的方法。对。因此,使用你的方法,你将不会有空单元格,并且大多数单元格至少有K/2个点。但是,使用我的方法,你最终会有空单元格,并且单元格只有很少的点。而且,没有任何东西表明你也不能将最大的单元格分成两组,将两者结合起来是的,我试过了,它(在递归cas中)很有帮助