Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 矩形内所有点的快速算法_Algorithm_Computational Geometry - Fatal编程技术网

Algorithm 矩形内所有点的快速算法

Algorithm 矩形内所有点的快速算法,algorithm,computational-geometry,Algorithm,Computational Geometry,给定二维空间中的一组不同点和一个矩形(所有四个点的坐标,与xy轴平行的边),如何快速找到矩形内的点 我对遍历所有点并查看哪个点在矩形内的基本解决方案不感兴趣。我要找的是一种算法,它可以让我在每个矩形上快速查询 我不在乎在预处理步骤中花费了多少时间。我所关心的是,在我处理完数据后,我得到了一个有用的结构,它可以为每个矩形提供快速的查询时间 例如,我知道我可以用O(logN)来计算一个矩形内有多少个点。这是因为我在开始时做了很多繁重的处理,然后每次用一个新的矩形查询处理过的数据,并在logN tim

给定二维空间中的一组不同点和一个矩形(所有四个点的坐标,与xy轴平行的边),如何快速找到矩形内的点

我对遍历所有点并查看哪个点在矩形内的基本解决方案不感兴趣。我要找的是一种算法,它可以让我在每个矩形上快速查询

我不在乎在预处理步骤中花费了多少时间。我所关心的是,在我处理完数据后,我得到了一个有用的结构,它可以为每个矩形提供快速的查询时间


例如,我知道我可以用O(logN)来计算一个矩形内有多少个点。这是因为我在开始时做了很多繁重的处理,然后每次用一个新的矩形查询处理过的数据,并在logN time中得到一个新的计数。我正在寻找一种类似的算法来查找实际点,而不仅仅是它们的计数。

我认为您应该将点存储在一个数据库中。我还没有计算出细节,但它应该允许基本上做一些类似于二进制搜索的事情,直接生成矩形内的点

如果您的点是群集的,即存在一个小区域中包含许多点的群集,而其他区域中不包含或很少包含点,则可能更好


我认为运行时复杂性应该是O(logN)。

您可以将点分组到扇区中。如果一个扇区完全在给定的矩形内或外,那么该扇区内的所有点也都在矩形内或外。如果某个扇区部分位于中,则必须在该扇区中搜索O(n)点,以检查它们是否位于矩形中。寻找搜索。

经典答案是kD树(本例中为2D树)

对于一个简单的替代方案,如果您的点分布足够均匀,您可以尝试网格化

为方形网格选择单元大小(如果问题是各向异性的,请使用矩形网格)。将每个点指定给存储在链接列表中的包含该点的栅格单元。执行查询时,查找矩形重叠的所有单元格,并扫描它们以遍历它们的列表。对于部分覆盖的单元格,需要执行矩形中的点测试

尺寸的选择很重要:太大可能导致需要测试的点太多;太小可能会导致太多空单元格。

您正在查找或范围查询

  • 当点集发生变化时,四叉树(或八叉树或16棵树…)更好,但您希望分布均匀。不需要进一步的平衡步骤,因为树的结构是固定的
  • kd树在固定点集上表现更好,即使分布不均匀。当点集更改时,很难(但并非不可能)执行自平衡步骤
  • AABB树(或胖AABB树)提供了一种快速的方法来测试重叠的形状,而不仅仅是点。AABB树偶尔需要一些平衡。当包含不断移动的对象时,常用的方法是使用“fat AABB-s”,这样就不必在每一帧中更新树
  • 仅按一个轴排序并使用二进制搜索(类似于abelenky建议的,但我认为进行第二个二进制搜索没有意义)是一个简单而优雅的解决方案,但如果按X轴排序,速度会很慢,所有的点都在一条与Y平行的线上。你必须对通过X的二元搜索匹配的点进行线性过滤。时间复杂度是最坏的情况
    O(n)
    ,但这种最坏的情况经常发生
所有这些算法都在平均
O(logn+k)
中运行查询,其中k是匹配点的计数


像Yves建议的那样,网格化可以在
O(k)
time中执行范围搜索,但仅当查询矩形的大小有界时。这是他们在中国经常做的事。即使在输入集没有边界的情况下也可以使用网格划分——只需根据网格坐标的散列值对存储桶进行固定计数即可。但是,如果查询矩形可以是任意大小,那么网格化是不可能的。

与其他答案一起,您还可以查看Morton代码(z顺序曲线排序)

对于静态数据,您甚至可以将整个点数据表示为数组


这篇论文还有一个相当复杂的不同“多维访问方法”的时间轴--

矩形是否旋转?如果不是,这只是一个简单的AABB检查:
If(p.x>=rect.x&&px。请看这篇文章:我不明白你是如何在LogN时间内提出这个建议的。对于N个点,你至少要通过所有N个点一次。你能得到的最好结果是O(N)。我在寻找快速查询时间。也就是说,我的点是给定的和固定的。从一个查询到另一个查询的变化是矩形。我在寻找每个矩形的快速查询时间(预处理步骤可能需要做任何事情,那就是做一次,我关心的是查询时间)。复杂性至少为O(logn+K)其中K是报告的点数;第二项可能超过第一项。你有没有一个快速链接来解释你的第二项?我直觉上会预期相反的结果。@Jenschauder没有,我没有,这只是直觉,有一个事实支持,有时你需要重新平衡树。事实上,重新平衡树可能不会产生任何效果e这么多时间。我会做一些研究并在某个时候测量方法。哦,我可能误解了你的观点。我理解为kd树在固定点集上的性能优于四叉树。但现在我认为你的意思是比改变点集更好?@Jenschauder sry不清楚。我的意思是kd树在你有一组固定的点。假设在一个大的搜索空间中有一个聚集点集。kd trees空间分区适应群集,而quadtree需要将整个搜索空间分成四个部分,直到到达群集。这意味着