有界线集合相交的高效算法
Posted
技术标签:
【中文标题】有界线集合相交的高效算法【英文标题】:Efficient algorithm for intersection of a collection of bounded lines 【发布时间】:2017-11-18 23:33:43 【问题描述】:我有一组成对的数字,需要有效地找到包含给定值的成对集合。
给定以下数字对的表示形式
public class Line
public double Start get; set; //is always < end
public double End get; set;
Lines
的集合可以在视觉上像下面这样布局(黑线)
垂直的红线是相交标准(只是一个简单的数字,比如 10.123)
我正在寻找一种有效的算法,该算法仅返回与红色相交的黑线,假设搜索执行的频率大于 Line
添加到集合的频率。 (显然假设集合很大)
到目前为止,我的最佳解决方案是
-
在创建到两个排序列表时插入行。一个排序在
Start
,另一个排序在End
对起始有序列表进行二分搜索,以查找起始大于交集条件的第一行的索引。 (理论上,包括该索引和该索引之后的所有线都不相交)
对最终有序列表重复 (2) 中的类似逻辑
比较索引并选择剩余迭代次数最少的列表来解决
手动遍历所选列表的其余部分以查找交叉点
【问题讨论】:
lines.Where(l => l.Start <= criteria && l.End >= criteria)
会不会太低效?还是我过于简单化了?
这需要点击集合中的每个项目。
根据有多少范围,将范围划分为范围桶(一个范围可以在多个范围桶中)可能会导致比二分查找更少的比较,并且可能更容易并行化跨度>
也许你想要Interval tree?
@dbc Ahh Interval Tree 完美地描述了我的确切问题,谢谢。我会找到一些实现并运行一些性能测试。它肯定比我的滚动解决方案更快。作为答案发布,我会接受。
【参考方案1】:
您的Line
类代表ℝ 中的interval。您有大量这样的间隔,并且希望在比线性时间更好的时间内找到与某个点重叠的那些。
interval tree 是满足您要求的一种可能解决方案:
查询需要O(log n + m)
时间,其中n
是区间总数,m
是与找到的查询点的重叠数。
构造需要O(n log n)
。
存储需要O(n)
空间。
Codeplex 的示例实现(我尚未测试)。对于其他人,请参阅C# Interval tree class。
要与相关结构segment tree 进行比较,请参阅What are the differences between segment trees, interval trees, binary indexed trees and range trees?。
【讨论】:
【参考方案2】:这可能应该通过两个并行搜索器来完成,但是... 由于您已经管理了两个列表,请尝试以下操作:
搜索第一个 .Start
值 > ValuePoint
。
(超出此索引的所有值显然无效)
int idx_start = Lines.FindIndex(x => x.Start > ValuePoint);
按 [.End] 的值对列表进行排序
鉴于您的列表已经排序,此排序永远不会是 O(n) 操作,
应该平均到O((i) log (i))
,其中i = Index
是找到的第一个值。
当然,i
可能是= n
EndComparer ecomp = new EndComparer();
Lines.Sort(0, idx_start, eComp);
EndComparer
:
public class EndComparer : IComparer<Lines>
public int Compare(Lines lineX, Lines lineY)
return lineX.End.CompareTo(lineY.End);
然后找到第一个.End
值>ValuePoint
int idx_end = Lines.FindIndex(0, idx_start, x => x.End > ValuePoint);
if (idx_end > -1)
//All values in the range [idx_end; idx_start] are valid
//If idx_end = 0 then all pre-selected values are valid [0; idx_start]
else
//All value in the range are non valid
【讨论】:
以上是关于有界线集合相交的高效算法的主要内容,如果未能解决你的问题,请参考以下文章