[英]i want to add speed ranges with some fine amounts and save them into database
..我的问题是我应该检查速度范围是否重叠,如果它们重叠,我应该显示一条消息,说明速度范围不能重叠。
Minimum Maximum Rate
1 15 10
16 25 15
将每个速度范围视为连续数字线上的线段。 为了找到所有重叠,请在每个线段重叠处对数字线进行分区。
首先,将每个范围分为起点和终点。 假设您的范围是:
(5,8) (1,5) (14,17) (3,4) (5,10)
为了清楚起见,我将给他们分配字母:
A=(5,8) B=(1,5) C=(14,17) D=(3,4) E=(5,10)
好的,现在,让我们将这些范围划分为离散的起点和终点:
A[start]=5, A[end]=8, B[start]=1, B[end]=5, C[start]=14, C[end]=...
等。
按值对这些点进行排序,如果值相等,则起点在终点之前,因此您将获得如下列表:
B[start]=1, D[start]=3, D[end]=4, A[start]=5, E[start]=5, B[end]=5, A[end]=8, ...
等
容易吧?
现在,只需遍历已排序的列表,并保留当前范围的列表即可。 每次到达[start]
时,都将该范围添加到列表中。 每次到达[end]
时,请将范围从列表中删除。
因此,对于上面的列表,您可以使用:
B[start]=1 add B => (B)
D[start]=3 add D => (B,D)
D[end]=3 remove D => (B)
A[start]=4 add A => (B,A)
E[start]=5 add E => (B,A,E)
B[end]=5 remove B => (A,E)
A[end]=8 remove A => (E)
... and so on
只要您的列表包含多个元素,那就是一个重叠。 因此,对于任何范围,您都可以准确确定哪些范围在任何特定点重叠。
假设您使用类似quicksort的算法对存在/结束点进行排序,即运行时间为O(n log n)
,并且检测到实际重叠时间是线性的,那么整个算法将在O(n log n)
。
如果对值进行排序:
然后,您可以依次遍历它们,并对照下一个检查范围。 重叠范围将在序列中彼此相邻。
在您的示例中:
但是请注意,此算法仅回答“是否有任何范围重叠”的问题,它不能为您提供所有重叠的组合。 例如,在上面的代码中,1-16和15-25重叠,但是在此实现中没有得到这种组合。
如果需要,则需要更智能的算法。
我在这里发布了一个Visual Studio 2008项目: SO2696398的Subversion存储库 。
主要的应用程序代码如下所示:
using System;
using System.Linq;
using LVK.Collections;
namespace SO2696398
{
public class Program
{
public static void Main(string[] args)
{
var ranges = new[]
{
new Range<int, double>(1, 15, 10),
new Range<int, double>(16, 25, 15),
new Range<int, double>(8, 22, 7),
};
var slices = ranges.Ordered<int, double>().Slice();
foreach (var slice in slices)
{
if (slice.Data.Length == 1)
continue;
Console.Out.WriteLine("overlap at " + slice.Start
+ "-" + slice.End + ": "
+ string.Join(" with ",
(from range in slice.Data
select range.ToString()
+ " [rate=" + range.Data + "]").ToArray()));
}
}
}
}
输出为:
overlap at 8-15: 1..15 [rate=10] with 8..22 [rate=7]
overlap at 16-22: 8..22 [rate=7] with 16..25 [rate=15]
希望这可以帮助。 项目的班级部分是我在主班级库中拥有的班级的一小部分。 如果您希望链接到完整的库,则可以从Subversion Repository for LVK for .NET下载并编译源代码。 此处使用的类来自LVK.Core项目。
您可以轻松地在数据库中实现此业务逻辑,以要求将来的任何应用程序都遵循此约束。
我将使用以下方式将逻辑实现为存储过程(或触发器):
CREATE PROCEDURE MyDatabase.spInsertSpeedRanges
@Min int,
@Max int,
@Rate int
AS
select top 1 *
from tblSpeedRanges
where (Minimum between @Min and @Max) or (Maximum between @Min and @Max)
if @@RowCount <> 0
return -1
else
insert into tblSpeedRanges (Minimum, Maximum, Rate) values (@Min, @Max, @Rate)
GO
然后在您的应用程序中,如果返回-1,则显示您选择的错误消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.