优化算法在2d道路(线)中找到交叉点

时间:2015-05-11 21:01:03

标签: java algorithm sorting big-o

我有一个代表道路的行列表,每条道路都有一个“StartingPoint”和一个“EndingPoint”。我的目标是找到每条道路的“下一步”道路。 如果道路的起点或终点位于另一条道路的起点或终点之上,那么道路就是另一条道路。例如:

道路A:起点:(0,0)和终点(2,0)
道路B:起点:(2,0)和终点(5,0)
C路:起点:(2,0)和终点(4,2)

所以道路接下来将是:

下一个{B,C}
B NEXT {A}
C NEXT {A}

我现在的algorthim通过比较道路的每个起点到另一条道路的起点和终点,在O(n ^ 2)中进行。怎样才能让这更快。我认为整理道路可能有用,但我不确定。请告诉我你的想法!

注意:那些使用Hashmap<Start/EndPoint,Road>解决方案的人仍然是O(N ^ 2)。

5 个答案:

答案 0 :(得分:3)

这取决于你想要对结果做什么。计算结果的大小为O(#roads^2)。这意味着如果你想迭代它,那么你最多需要O(#roads^2)。这就是说,如果你只想回答诸如“返回给定道路的所有邻接”之类的问题,那么你可以使用你实现的算法在O(#roads)中做到这一点。

答案 1 :(得分:0)

在Java中,HashMap<XYPoint, HashSet<Road>> endPoints和另一个HashMap<Road, HashSet<Road> next就足够了;假设您的Road对象有一个结尾并且开始XYPoint s。逻辑如下:

 for each road R,
     add it, using its starting point, to the endPoints map; and
             for each road X with a co-incident endpoint, 
                 next.put(R, X); next.put(X, R);                     
     add it, using its ending point, to the map endPoints map; and
             for each road X with a co-incident endpoint, 
                 next.put(R, X); next.put(X, R);                     

在此过程结束时,您的next地图将包含每条道路的下一条道路。您只需迭代此映射即可生成所需的输出。

如果没有下一条道路,则算法为O(n)。在最坏的情况下(所有道路都有相同的起点和终点),它是O(n ^ 2);你可以通过为你的Roads使用合适的equals / hashcode来消除这种情况,代价是一些额外的复杂性(你需要计算重复次数)。

答案 2 :(得分:0)

在我看来,最简单的方法是创建一个类Cell,它代表某个点,如(x; y)。覆盖Cell的equals和hashCode,然后简单地将Cell对象存储在HashMap中,以保证检索其元素的高速度。

答案 3 :(得分:0)

有一个O(n log n)算法,我不确定是否有更好的算法。

你可以:

1)创建一个Point类,它由一个2D点和一个指向道路的指针组成,它具有一个端点(起点或终点)。

2)创建一个比你的道路集合大两倍的数组

3)循环遍历所有道路,并添加一个表示数组的起点或终点的点 - 将点指向返回创建它的道路。

4)使用您选择的排序对数组进行排序。你可以使用很多排序功能,但是既然你要编写代码,我会说你先用y排序,然后在相同的y上用x来抢劫。所以:

if ( a.y < b.y ) return -1;
if ( a.y > b.y ) return 1;
if ( a.x < b.x ) return -1;
if ( a.x > b.x ) return 1;
return 0;

如果你关心速度,那么你应该把它重写为非分支。

5)相邻点可能相同。肯定不是非相邻点。在O(n)时间内运行有序数组。积分返回他们的道路。结合你认为合适。

答案 4 :(得分:0)

如果你允许3件事,你的最终结果的存储不必是大小为O(道路^ 2):

  • 为与道路起点和终点重叠的道路存储单独的子列表。您可以将两个列表连接在一起,以便在查找时获得道路的完整下一个列表,或者迭代一个列表然后迭代另一个列表。
  • 道路之间的分享清单。一条道路的起点列表可能是另一条道路的起点或终点列表。换句话说,对于每个点,都有一个列表,其中包含所有道路的开始或结束。
  • 允许道路成为其自己的列表的成员(并在检索列表时忽略它)。

您需要的哈希映射是HashMap<XYPoint, List<Road>>

对于每条道路,存储List<Road> startList和endList

算法是(伪代码):

For each road in list
    For point in [start, end]
        Look up List<Road> roadlist from hash map based on point X,Y
        If null then
            roadlist = new List<Road>
            add road to roadlist
            add roadlist to hash map
        else
            add road to roadList
        set roadList as either road.startList or road.endList

您只需将每条道路添加到列表两次。假设哈希查找和添加是O(1)那么这应该是O(n)。

相关问题