Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.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#_.net - Fatal编程技术网

C# 正在查找类似哈希集的内容,但具有一系列值作为键?

C# 正在查找类似哈希集的内容,但具有一系列值作为键?,c#,.net,C#,.net,我想知道是否有类似于HashSet的东西,但是由一系列的值进行键控 例如,我们可以添加一个项,该项被设置为100到4000之间的所有整数的键。如果我们使用100到4000之间的任何键,例如287,则会返回此项 我希望查找速度非常接近HashSet,即O(1)。可以使用二进制搜索来实现这一点,但是这对于需求来说太慢了。我希望尽可能多地使用标准的.NETAPI调用 更新 这很有趣: 它的时间复杂度为O(log(N)),其中N是间隔数,所以它并不完全是O(1),但它可以用来构建一个工作实现 我不相信已

我想知道是否有类似于HashSet的东西,但是由一系列的值进行键控

例如,我们可以添加一个项,该项被设置为100到4000之间的所有整数的键。如果我们使用100到4000之间的任何键,例如287,则会返回此项

我希望查找速度非常接近HashSet,即O(1)。可以使用二进制搜索来实现这一点,但是这对于需求来说太慢了。我希望尽可能多地使用标准的.NETAPI调用

更新

这很有趣:


它的时间复杂度为O(log(N)),其中N是间隔数,所以它并不完全是O(1),但它可以用来构建一个工作实现

我不相信已经有了这样的结构。您可以实现类似RangeDictionary的功能:

class RangedDictionary {

   private Dictionary<Range, int> _set = new Dictionary<Range, int>();

   public void Add(Range r, int key) {
      _set.Add(r, key);
   }

   public int Get(int key) {
      //find a range that includes that key and return _set[range]
   }
} 

struct Range {  
   public int Begin;
   public int End;
   //override GetHashCode() and Equals() methods so that you can index a Dictionary by Range
}
类范围字典{
专用词典_set=新词典();
公共无效添加(范围r,整数键){
_集合。添加(r,键);
}
公共整数获取(整数密钥){
//找到包含该键的范围并返回_set[range]
}
} 
结构范围{
公共服务开始;
公共互联网终端;
//重写GetHashCode()和Equals()方法,以便可以按范围索引字典
}

编辑:更改为HashSet to Dictionary

以下是一个您可以尝试的解决方案。然而,它假设了一些要点:

  • 没有范围重叠
  • 当您请求一个数字时,它实际上在一个范围内(无错误检查)
根据你所说的,这个是O(N),但是我认为你可以不费吹灰之力就把它变成O(log(N))

其思想是,一个类将处理范围的事情,它将基本上把给定给它的任何值转换为其范围的下边界。这样,您的哈希表(这里是一个字典)包含低边界作为键

public class Range
{
    //We store all the ranges we have
    private static List<int> ranges = new List<int>();
    public int value { get; set; }

    public static void CreateRange(int RangeStart, int RangeStop)
    {
        ranges.Add(RangeStart);
        ranges.Sort();
    }

    public Range(int value)
    {
        int previous = ranges[0];
        //Here we will find the range and give it the low boundary
        //This is a very simple foreach loop but you can make it better
        foreach (int item in ranges)
        {
            if (item > value)
            {
                break;
            }
            previous = item;
        }
        this.value = previous;
    }

    public override int GetHashCode()
    {
        return value;
    }
}
公共类范围
{
//我们存储所有的范围
私有静态列表范围=新列表();
公共int值{get;set;}
公共静态void CreateRange(int RangeStart、int RangeStop)
{
范围。添加(范围开始);
ranges.Sort();
}
公共范围(int值)
{
int previous=范围[0];
//在这里,我们将找到范围,并给出它的低边界
//这是一个非常简单的foreach循环,但您可以使其更好
foreach(范围内的int项)
{
如果(项目>值)
{
打破
}
先前=项目;
}
this.value=以前的值;
}
公共覆盖int GetHashCode()
{
返回值;
}
}
下面是对它的测试

class Program
{
    static void Main(string[] args)
    {
        Dictionary<int, int> myRangedDic = new Dictionary<int,int>();
        Range.CreateRange(10, 20);
        Range.CreateRange(50, 100);

        myRangedDic.Add(new Range(15).value, 1000);
        myRangedDic.Add(new Range(75).value, 5000);

        Console.WriteLine("searching for 16 : {0}", myRangedDic[new Range(16).value].ToString());
        Console.WriteLine("searching for 64 : {0}", myRangedDic[new Range(64).value].ToString());

        Console.ReadLine();
    }
}
类程序
{
静态void Main(字符串[]参数)
{
Dictionary myRangedDic=新字典();
范围。CreateRange(10,20);
创建范围(50100);
myRangedDic.Add(新范围(15).value,1000);
myRangedDic.Add(新范围(75).value,5000);
WriteLine(“搜索16:{0}”,myRangedDic[new Range(16).value].ToString());
WriteLine(“搜索64:{0}”,myRangedDic[新范围(64.value.).ToString());
Console.ReadLine();
}
}
我不相信你真的可以低于O(Log(N)),因为你无法立即知道一个数字在哪个范围内,你必须始终将它与下限(或上限)进行比较

如果你有预先确定的范围,那会更容易做到。i、 e.如果你的范围是每几百个,通过计算它的模100,很容易找到任何数字的正确范围,但是这里我们可以假设没有,所以我们必须检查


要使用此解决方案深入到Log(N),只需将foreach替换为一个循环,该循环将查看数组的中间部分,然后每次迭代都将其拆分为两个…

为什么不使用HashSet和匹配所需逻辑的比较器呢?但是HashSet没有键。是否知道范围的任何信息,或者它们可以是任何信息?如果我理解正确,您需要多个键(一个整数范围)链接到同一项?如果这是正确的,我可能有一个解决方案,但我不确定我是否理解正确。可能的副本我在msdn文档中找不到任何对
哈希集的引用。我是否遗漏了什么,或者这是来自第三方图书馆的,或者你真的想在这里使用词典?谢谢你的回答。然而,这似乎要求您在检索项目时知道范围,但我们不知道该点的范围!另外值得注意的是,“找到包含该键的范围并返回_set[range]”的过程不会像OP要求的那样是O(1),我想…@Chris:yes,我是指字典。我们在检索时不需要知道范围。我们只需要找到一种基于键检索范围(ranges?)的方法。是的,这可能不止O(1),但我看不到更好的解决方案。(除非您对1-100、101-200等范围有一个预定义的模式…)发现有一个专门的数据结构(尽管可能没有在标准的.NET API中实现)来实现这一点。这是一个片段树。它以对数复杂度查找一个值的范围(就像这里的bin搜索一样)。但是,这些范围可以在段树中重叠。OP对范围不能重叠的限制能帮助我们降低复杂性吗?我不确定。