我有很多x,y点,每个x,y点都有一些与之相关的额外数据。这个额外的数据我将存储在结构中。 我的应用程序要求给定任何一个点,我将不得不在该点周围的矩形区域内找到多少其他点(此点位于矩形的中心)。
我想到的一个逻辑是将所有x点存储为地图A中的键,并将所有y点作为另一个地图B中的键存储。 地图A将x作为键,y值作为值。 映射B将y作为键,关联的结构作为值。
这样,如果给定的点是(10.5,20.6),我可以使用upper_bound(10.5 + RECTANGLE_WIDTH)和lower_bound(10.5-RECTANGLE_WIDTH)来查找矩形内的x值范围和相应的y值,找出y值是否在20.6的+ - 范围内。
我使用地图的全部意义因为我有大量的x,y点存储,并且必须每两秒进行一次搜索。所以我不得不使用log(n)搜索map。 我觉得这可以以更有效的方式完成。建议?
答案 0 :(得分:7)
这是quadtree的典型应用。四叉树有助于在O(log(n)+ m)中查找位于矩形中的m个点,其中n是点的总数。
编辑:您使用地图的方法效率不高。对于随机分布的点,它将具有O(sqrt(n))平均复杂度和O(n)最坏情况。
答案 1 :(得分:0)
如何将点存储为指向这些结构的简单二维数组,当需要找到一个点x时,它就是一个简单的索引操作。任何其他点(x + a,y + b)都是如此。
答案 2 :(得分:0)
如果使用std :: points的点,则查找将始终为O(log N),其中N是您拥有的点数。
您的另一个选择是将您的搜索空间划分为多个桶,并将您的观点分为多个桶。然后在矩形中计算:
对于那些有重叠的人,你可以在你的集合中查找O(M),如果你使用每个桶的正确的集合类型,但是M应该小于N.甚至可能M很少超过少数情况下你可以线性地检查它们。
确定哪些存储桶重叠是一个恒定的时间操作,但是你必须线性地运行它们(甚至要检查它们是否为空),因此它们中的太多可能也是一个问题。
答案 3 :(得分:0)
第一个观察结果是std::map
在任何情况下都不是最有效的结构。你的输入几乎是固定的,显然(来自评论)。在这种情况下,排序std::binary_search
上的std::vector
效率更高。 std::map
相对于排序std::vector
的主要好处是插入是O(log N)而不是O(N),并且您不需要它。
下一个观察结果是,你可以在第一阶段可能会有点不准确。您的输出集可能会比总点数小很多(否则线性搜索将按顺序排列)。但假设是这种情况,您可能会因为舍入矩形而受益。这将产生更多的候选点,然后根据精确的边界进行检查。
例如,如果您的点在(0,0)和(200,300)之间的XY平面中随机分布,则可以创建一个20x30矩阵,每个矩阵保持一个大小为(10,10)的子区域。如果您现在需要从(64,23)到(78,45)的矩形中的点,则需要检查子区域[6,2], [6,3], [6,4], [7,2], [7,3] and [7,4]
- 仅600中的6个。在第二步中,您将丢弃结果as(61,25)。