基于矩形的点搜索优化

时间:2014-11-23 03:36:59

标签: java search optimization hashmap interval-tree

我有一组房间和通道,我可以将其转换为矩形(x,y,宽度,高度)或点(x,y)列表。 RoomPassage都扩展了Pointable接口。对于Room类,实现了getPoints()方法为

public Set<Point> getPoints() {
    Set<Point> array = new HashSet<Point>();
    for (int i = 0; i < width; i++) {
        for (int j = 0; j < height; j++) {
            array.add(new Point(x + i, y + j));
        }
    }
    return array;
}


问题:
我必须确定给定Pointable所属的Point。没有房间相交。我最初使用HashMap<Point,Pointable>将每个PointPointable相关联,后者能够在O(n)时间内快速访问答案。但是,现在有必要在生成级别时多次重新计算HashMap

此时,使用HashMap(考虑到生成和访问)还是应该使用其他方法(例如一组二维间隔树)是否更有效?

1 个答案:

答案 0 :(得分:1)

  

此时,使用HashMap(考虑到生成和访问)还是应该使用其他方法(例如一组二维区间树)是否更有效?

除了进行测量的人之外,没人知道。这一切都取决于您需要更新数据的频率,更改的频率以及查询的频率。

还有Room的大小。有几点,HashMap在一个典型场景中胜出,其中有数千个,更新积分的开销占主导地位。


你不能为所有Point使用数组吗?如果是这样,那么它肯定会比HashMap更快,特别是对于更新(除非它真的很大)。


这可能有用也可能没用。

实际上,不仅每个Room都有Point个,而且每个Point可能只有一个Room(n:1)。如何实施,这是一个不同的问题。

鉴于此,我们遇到了一个标准问题:如果您双向链接,则必须保持两个链接同步。最简单的解决方案是使setter(“adders”/“removers”)尽可能私有,只从方法中调用它们

void link(Room room, Point point) {
    Room oldRoom = point.getRoom();
    if (oldRoom!=null) oldRoom.removePoint(point);
    room.addPoint(point);
    point.setRoom(room);
}

您从PointRoom的链接是外部的,但这几乎不会改变任何内容(除了保持Point更小,可能更清晰,并为每次访问添加HashMap的微小开销)

它通常也是最快的,因为通常会有更多的查询而不是更新。您的问题是更新费用按Room大小按比例放大。 如果没有您告诉我们某些数据,则无法估算。


由于太多的点和房间尺寸变化太大,您可以将点坐标舍入到某个n的倍数,并保持一个数组,其中包含与网格相交的所有房间的集合。您可以像以前一样继续进行,但是更新开销会降低几乎由房间区域(*)给出的因素和搜索开销更高,因为您必须从集合中选择真正匹配的房间(如果有的话)。

(*)对于未与网格对齐的房间,交叉矩形的数量明显更高。