Java 在二维道路(线)中查找交点的优化算法

Java 在二维道路(线)中查找交点的优化算法,java,algorithm,sorting,big-o,Java,Algorithm,Sorting,Big O,我有一个代表道路的线列表,每条道路都有一个“起点”和一个“终点”。我的目标是找到每一条路的“下一条”路如果一条道路的起点或终点位于另一条道路的起点或终点之上,则该道路是另一条道路的下一条道路。例如: 道路A:起点:(0,0)和终点(2,0) 道路B:起点为:(2,0)终点为(5,0) 道路C:起点为:(2,0)终点为(4,2) 因此,接下来的道路将是: 下一个{B,C} B下一个{A} C下一个{A} 我目前的算法是在O(n^2)中通过比较一条路的每个起点和另一条路的起点和终点来实现的。如何才能

我有一个代表道路的线列表,每条道路都有一个“起点”和一个“终点”。我的目标是找到每一条路的“下一条”路如果一条道路的起点或终点位于另一条道路的起点或终点之上,则该道路是另一条道路的下一条道路。例如:

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

因此,接下来的道路将是:

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

我目前的算法是在O(n^2)中通过比较一条路的每个起点和另一条路的起点和终点来实现的。如何才能让这更快。我认为整理道路可能有用,但我不确定。请告诉我你的想法


注意:那些说使用
Hashmap的人
你的解决方案仍然是O(N^2)。

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

在Java中,一个
HashMap端点
,另一个
HashMap在我看来,最简单的方法是创建一个类单元格,它将表示(x;y)这样的某个点。覆盖单元格的equals和hashCode,然后简单地将单元格对象存储在一个HashMap中,以保证快速检索其元素。

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

你可以:

1) 创建由二维点和指向其端点(起点或终点)的道路的指针组成的点类

2) 创建一个两倍于道路集合的数组

3) 在所有道路中循环,并将代表起点或终点的点添加到阵列中-将所述点返回到创建该点的道路

4) 使用您选择的排序对阵列进行排序。你可以使用很多排序函数,但既然你在写代码,我会说你使用的是一个先按y排序,然后用x在相等的y上进行tiebreak的函数。因此:

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;
if(a.yb.y)返回1;
如果(a.xb.x)返回1;
返回0;
如果你关心速度的话,你可能应该把它重写为非分支


5) 相邻点可能相同。非相邻点当然不是。在O(n)时间内运行有序数组。点指的是他们的道路。根据需要进行组合。

如果允许以下三种情况,则最终结果的存储大小不必为O(道路^2):

  • 为重叠道路起点和终点的道路存储单独的子列表。在查找道路时,您可以将两个列表连接在一起,以获得道路的完整下一个列表,或者遍历其中一个列表,然后再遍历另一个列表
  • 在道路之间共享列表。一条道路的起点列表可能是另一条道路的起点或终点列表。换句话说,对于每个点,都有一个单一的列表,其中列出了从该点开始或结束的所有道路
  • 允许道路成为其自己列表的成员(在检索列表时忽略它)
您需要的哈希映射是
HashMap

对于每条道路,存储
List
starlist和endList

算法是(伪代码):

列表中每条道路的

对于[开始,结束]中的点
基于点X,Y从散列图中查找列表道路列表
如果为空,则
路演名单=新名单
将道路添加到道路列表中
将道路列表添加到哈希映射
其他的
将道路添加到道路列表中
将roadList设置为road.strist或road.endList

只需将每条道路添加到列表中两次。假设散列查找和加法为O(1),那么这应该是O(n)。

您是否可以在使用起点/终点作为关键点的多重地图中“索引”道路,以及将该点作为值的所有道路?从那里,建立一个有向图应该很容易。而且我不明白你说的“每条路都有它的起点和终点”是什么意思。“你为什么不让它向两个方向移动呢?”LysenkoAndrii,因为一条路可以是两条路way@HiradRoshandel坐标范围有限制吗?对x,y说(x,y)在我的例子中,不是O(1)来查找nexts,我想查找所有道路的nexts,所以它再次变成O(n^2)来遍历所有道路和所有集合否?是的,技术上这是O(n)来查找单个道路的下一个,因为addAll调用。所以找到所有的路都是O(n^2),它比你的好。我的也是O(n^2)。我使用嵌套for循环。这和上面的Benjy Kessler答案不一样吗?还是O(n^2)不?这很相似——我在他发帖之前就开始写了,但后来写完了。
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;
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