我正在寻找一种为矩形提供索引的数据结构。我需要插入算法尽可能快,因为矩形将在屏幕上移动(想想用鼠标拖动矩形到新位置)。
我研究过R-Trees,R + Trees,kD-Trees,Quad-Trees和B-Trees,但是根据我的理解,插入通常很慢。我更喜欢以亚线性时间复杂度进行插入,所以也许有人可能会证明我对列出的数据结构中的任何一个都不对。
我应该能够在数据结构中查询矩形在点(x,y)或矩形与矩形(x,y,宽度,高度)相交的位置。
编辑:我想要插入如此之快的原因是因为如果你想到一个矩形在屏幕上移动,它们将不得不被删除然后重新插入。
谢谢!
答案 0 :(得分:3)
我使用多尺度网格方法(相当于某种形式的四叉树)。
我假设您正在使用整数坐标(即像素)并且有足够的空间来容纳所有像素。
有一个矩形列表数组,每个像素一个。然后,二乘二,然后再做一次。再次,一次又一次,直到你有一个覆盖所有内容的像素。
现在,关键是您将矩形插入到与矩形大小匹配的级别。这将是(像素大小)〜= min(高度,宽度)/ 2。现在,对于每个矩形,您只需要在列表中进行少量插入操作(您可以通过常量将其绑定在上面,例如选择具有4到16像素的内容)。
如果要在x,y处查找所有矩形,请在最小像素列表中查找,然后在包含它的2x2分级像素列表中查找,然后在4x4等中查找;你应该有log2(像素数)步骤来查看。 (对于较大的像素,你必须检查(x,y)是否真的在矩形中;你希望它们中的大约一半在边界上成功,并且所有这些都在矩形内成功,所以你期望与直接查找像素相比,工作量不会超过2倍。)
现在,插入怎么样?这非常便宜 - O(1)将自己放在列表的前面。
删除怎么样?那更贵;您必须浏览并修复您输入的每个像素的每个列表。大约相同大小的空间和中该位置重叠的矩形数量大约是O(n)。如果你有大量的矩形,那么你应该使用其他一些数据结构来保存它们(哈希集,RB树等)。
(请注意,如果您的最小矩形必须大于像素,则不需要实际形成多尺度结构一直到像素级别;只需向下移动直到最小的矩形不会在内部无望地丢失您的分档像素。)
答案 1 :(得分:1)
这可能是一个扩展的评论而不是答案。
我对你真正想要的东西感到有点困惑。我猜你想要一个数据结构来支持快速回答问题,比如'给定矩形的ID,返回它的当前坐标'。是对的吗 ?
或者你想回答'哪个矩形在位置(x,y)'?在这种情况下,尺寸与显示器的高度和宽度相匹配的数组可能就足够了,数组中的每个元素都是该像素上矩形的(可能是短的)列表。
但是你要声明你需要一个插入算法尽可能快地应对不断移动的矩形。如果您在屏幕上只有10个矩形,那么您可以简单地使用包含每个矩形坐标的10个元素数组。然后,更新它们的位置不需要任何插入数据结构。
有多少个矩形?它们创建的速度有多快?并被摧毁?你想如何应对重叠?矩形只是一个边界,还是包含内部?
答案 2 :(得分:1)
你提到的数据结构非常复杂:特别是B-Tree应该很快(插入成本随着项目数量的对数而增长)但不会加速你的交集查询。
忽略这一点 - 并希望最好 - 空间数据结构分为两部分。第一部分告诉您如何从数据构建树结构。第二部分告诉您如何跟踪每个节点上的信息,这些信息描述了存储在该节点下面的项目,以及如何使用它来加速查询。
您通常可以捏造关于在每个节点上跟踪信息的想法,而不使用关于如何构建树的(昂贵)想法。例如,您可以通过对其点的坐标进行位交错来为每个矩形创建一个键,然后使用完美的普通树结构(例如B树或AVL树或红黑树)来存储它,同时仍然保持每个节点的信息。实际上,这可能足以加快您的查询速度 - 尽管在实际数据上实施和测试之前,您无法说出这一点。大多数方案中树木构建指令的目的是提供性能保证。
两个后记:
1)我喜欢Patricia树 - 它们相当容易实现,添加或删除条目不会对树结构造成太大影响,因此您不需要做太多工作来更新存储在节点中的信息。 / p>
2)上次我看了一个窗口系统时,它根本没有打扰任何这些聪明的东西 - 它只保留了一个项目的线性列表,并在需要时一直搜索它:那是足够快。