Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在范围列表中搜索数字的最快方法_C#_Performance_Algorithm_C# 4.0_Optimization - Fatal编程技术网

C# 在范围列表中搜索数字的最快方法

C# 在范围列表中搜索数字的最快方法,c#,performance,algorithm,c#-4.0,optimization,C#,Performance,Algorithm,C# 4.0,Optimization,我有以下代码来查找范围列表中数字的匹配项 public class RangeGroup { public uint RangeGroupId { get; set; } public uint Low { get; set; } public uint High { get; set; } // More properties related with the range here } public class RangeGroupFinder { p

我有以下代码来查找范围列表中数字的匹配项

public class RangeGroup
{
    public uint RangeGroupId { get; set; }
    public uint Low { get; set; }
    public uint High { get; set; }
    // More properties related with the range here
}

public class RangeGroupFinder
{
    private static readonly List<RangeGroup> RangeGroups=new List<RangeGroup>();

    static RangeGroupFinder()
    {
        // Populating the list items here
        RangeGroups.Add(new RangeGroup { RangeGroupId = 0, Low = 1023238144, High = 1023246335 });
        RangeGroups.Add(new RangeGroup { RangeGroupId = 0, Low = 1023246336, High = 1023279103 });
        RangeGroups.Add(new RangeGroup { RangeGroupId = 0, Low = 1023279104, High = 1023311871 });
        RangeGroups.Add(new RangeGroup { RangeGroupId = 0, Low = 1023311872, High = 1023328255 });
        RangeGroups.Add(new RangeGroup { RangeGroupId = 0, Low = 1023328256, High = 1023344639 });
        RangeGroups.Add(new RangeGroup { RangeGroupId = 0, Low = 1023344640, High = 1023410175 });
        RangeGroups.Add(new RangeGroup { RangeGroupId = 0, Low = 1023410176, High = 1023672319 });
        RangeGroups.Add(new RangeGroup { RangeGroupId = 0, Low = 1023672320, High = 1023688703 });
        RangeGroups.Add(new RangeGroup { RangeGroupId = 0, Low = 1023692800, High = 1023696895 });
       // There are many more and the groups are not sequential as it can seen on last 2 groups
    }

    public static RangeGroup Find(uint number)
    {
        return RangeGroups.FirstOrDefault(rg => number >= rg.Low && number <= rg.High);
    }
}
公共类范围组
{
公共uint RangeGroupId{get;set;}
公共uint Low{get;set;}
公共uint High{get;set;}
//更多与此范围相关的属性
}
公共类测距仪
{
私有静态只读列表范围组=新列表();
静态测距仪()
{
//在此处填充列表项
添加(新的RangeGroup{RangeGroupId=0,低=1023238144,高=1023246335});
添加(新的RangeGroup{RangeGroupId=0,低=1023246336,高=1023279103});
添加(新的RangeGroup{RangeGroupId=0,低=1023279104,高=1023311871});
添加(新的RangeGroup{RangeGroupId=0,低=1023311872,高=1023328255});
添加(新的RangeGroup{RangeGroupId=0,低=1023328256,高=1023344639});
添加(新的RangeGroup{RangeGroupId=0,低=1023344640,高=1023410175});
添加(新的RangeGroup{RangeGroupId=0,低=1023410176,高=1023672319});
添加(新的RangeGroup{RangeGroupId=0,低=1023672320,高=1023688703});
添加(新的RangeGroup{RangeGroupId=0,低=1023692800,高=1023696895});
//还有很多,而且这些组并不像在最后两组中看到的那样是连续的
}
公共静态范围组查找(uint编号)
{

返回RangeGroups.FirstOrDefault(rg=>number>=rg.Low&&number,如果只填充列表一次,则可以执行以下魔术:

  • 使用

排序需要O(Nlog(N))时间,并且只执行一次。二进制搜索需要O(log(N)),对10万个项目最多进行17次比较。

因为您指出
范围组
是按
范围组的顺序添加的。低
并且它们不重叠,所以您不需要进行任何进一步的预处理。您可以在
范围组
列表上进行二进制搜索以查找范围(警告:未完全测试,您需要检查一些边缘条件):

公共静态范围组查找(uint编号){
int position=RangeGroups.Count/2;
int步长=位置/2;
while(true){
如果(步长==0){
//找不到。
返回null;
}
if(范围组[位置].高<数字){
//向下搜索。
位置-=步长;
}else if(范围组[位置].Low>number){
//搜索。
位置+=步长;
}否则{
//找到了!
返回范围组[位置];
}
步长/=2;
}
}


最坏情况下的运行时间应该在O(log(N))左右,其中N是范围组的数量。

在两个不同的数组中对范围进行两次排序。一次按范围中的最小值排序,一次按范围中的最大值排序。然后进行两次二进制搜索,保存与任一约束匹配的范围。最后,对两组可能性进行一组交集。

可以使用已排序的列表并进行排序二进制搜索。这样可以减少与O(logN)的比较次数。

是为满足您的要求而创建的。

使用SortedList类可能会提高性能。您是否希望返回包含该数字的任何范围,或者该范围必须匹配任何条件(例如,最早添加的)?仅匹配条件的范围,所有范围都是唯一的,并按低的顺序添加,它们不会重叠。我建议使用按低值排序的树结构,而不是列表。顺便说一句,如果您正在搜索,查找术语“间隔”可能会比“范围”给出更好的结果在这种情况下,普通的二进制搜索不起作用。要考虑的范围既低又高。列表已经排序了,据我所知,为了能够使用二进制搜索,我需要知道我在找什么。也许,如果你能给二进制搜索一个例子,它会。帮助,谢谢。@MennanKara让我试着拿出一个示例。你能发布一些你如何填充这个列表的实例吗?你的算法需要超过O(logn)。你需要的是该值也比max低。@oleksii添加了一些示例数据,通常我从应用程序的数据库_Start()填充它+1在代码中,二进制搜索适用于范围,例如向下搜索时勾选high,向上搜索时勾选low。实际上,我对范围的数量错了,我的列表中有500多万个条目,所以我想知道使用TPL是否会提高性能(运行此代码的服务器有64个内核)。那么代码看起来会是什么样子呢?:)@MennanKara如果搜索是你主要做的事情,那么你也可以在不进一步修改算法的情况下对每个核心执行一次搜索。如果你真的想确保每次搜索花费尽可能少的时间,你可以将
RangeGroups
分成64个子组,并在每个子组的每个核心内执行并行搜索核心。但您不会获得64倍的性能提升。非常感谢,在问题末尾添加了测试结果:)除了范围不重叠没有必要这么远。你需要2次二进制搜索吗?我想他提到没有任何间隔重叠。好的,让我更清楚地说明一下。他按顺序添加这些间隔,它们不重叠。所以你有一个排序列表。续:搜索排序列表需要O(logN)如果不检查所有间隔,则无法执行此操作。您可以在logn中执行此操作,但间隔不重叠。@alinsoar问题中提到,间隔不重叠。间隔树相对于二进制搜索的好处在于,当您有重叠的间隔时。在这种情况下,没有重叠。二进制搜索
public static RangeGroup Find(uint number) {
    int position = RangeGroups.Count / 2;
    int stepSize = position / 2;

    while (true) {
        if (stepSize == 0) {
            // Couldn't find it.
            return null;
        }

        if (RangeGroups[position].High < number) {
            // Search down.
            position -= stepSize;

        } else if (RangeGroups[position].Low > number) {
            // Search up.
            position += stepSize;

        } else {
            // Found it!
            return RangeGroups[position];
        }

        stepSize /= 2;
    }
}