我应该使用什么空间索引算法?

时间:2012-10-01 18:43:16

标签: ios algorithm mkannotation kdtree spatial-index

我想为我的MKAnnotations实现一些空间索引数据结构之王。 当我尝试根据距离标准过滤它们时非常慢(3-4k的位置,目前使用简单的双for非常慢......)。

我想创建MKAnnotations的集群,以确定它是否接近另一个集群。此外,这些位置处于某种(创建)顺序,并且需要“先前”/“下一步”功能来“跳跃”(这不是必须的)。 我已经阅读过有关kd-treer-tree结构的内容,它们似乎都符合快速距离/邻居获取过滤/群集的选项,但我不确定哪种最适合我或者是否也是其他选择。 我应该使用什么算法/数据结构?

更新:我将这些位置存储在Core Data数据库中,它们代表一条路径。打开地图时,它们被提取到一个数组中,然后我只使用该数组进行距离计算和注释创建。 当用户移动/缩放地图时,我会遍历它们并确定需要在地图上更改的内容,因此整个内容都是静态的。据我了解,如果我要使用树,我可以在那里存储位置,当发生缩放/移动时,我只搜索它并获得新区域中的那些。这是真的 ?

即使在动态情况下,当我可以向此数组添加新位置时,它也只是一次插入而且很少发生。

2 个答案:

答案 0 :(得分:8)

这很大程度上取决于您的使用模式是什么(我的写入方式,例如内存中或磁盘上)以及数据的外观(就是它的分布方式)

R-tree很好,因为它们是平衡的,并允许更新。我的经验中的R * -tree明显优于其他变体,因为它具有分裂策略。好处是它产生比其他策略更多的方形页面,因此对于许多查询,您将需要扫描更少的页面。

如果你是内存和静态的话,kd-tree很好。更新它们非常糟糕,您需要经常重建索引。

如果您的数据不经常更改,则R树的批量加载效果非常好。您可以执行 Sort-Tile-Recursive 批量加载,这实际上需要(部分)对X和Y上的数据进行交替排序,因此构建树需要较低的O(n log n);非常类似于批量加载kd树,除了你多次拆分而不是二进制拆分。这很受欢迎。

此外,您可以跟踪每个页面中的对象数量。在地图上显示内容时,您可能希望在页面在屏幕上显示太小(即小于标记)时提前停止。此时,您不会扫描该页面,而只会获取对象的数量并将其显示为聚簇标记,直到用户放大。

对于2D数据,使用有限值域,不要忽略简单的事情。 Quadtrees也可以很好地工作!简单性可以使优化事物变得更加容易。或者是经典的网格方法。如果您的用户倾向于在一个区域中传播他们的注释(而不是将它们全部放在一个地方),您可以只计算整数x,y网格坐标,然后哈希它们并为每个网格单元格创建一个列表。

答案 1 :(得分:0)

我不是iOS开发人员,但我查看了文档并发现了这个:

  

<强> MKMapView.annotationsInMapRect:

     

返回位于指定地图矩形中的注释对象。

     

(NSSet *)annotationsInMapRect:(MKMapRect)mapRect

     

<强>参数

     
      
  • mapRect :地图中您要搜索注释的部分。
  •   
     

返回值   注释对象的集合,位于mapRect。

中      

<强>讨论   此方法提供了一种快速检索地图特定部分中的注释对象的方法。这种方法比自己在注释属性中对对象进行线性搜索要快得多。

这表明NKMapView已经在空间索引结构中组织注释。这种方法能满足您的需求吗?

如果没有,我会寻找任何2D空间索引结构的现有开源实现,并选择具有最佳文档,最干净的界面等的实现,而不是担心效率。如果你需要编写代码表,我认为四叉树是最容易实现的。另一方面,the Wikipedia article on R-tree似乎更专门针对映射而不是K-D树或四叉树。