快速找到SortedDictionary中第一个未使用的密钥?

时间:2014-12-29 12:49:08

标签: c# .net key sorteddictionary

如果我有SortedDictionary<int, object>,找到当前未使用的最低密钥的最快方法是什么?显然,我们可以从0-&gt; int.MaxValue迭代一个计数器i并在!Keys.Contains(i)时转义,但除非我们很幸运并且第一个备用键恰好在序列的早期,否则这将非常慢钥匙也许甚至一个不同的.NET类已经为我们做了这个?

4 个答案:

答案 0 :(得分:2)

所以,如果我理解正确,那么密钥可以是0int.MaxValue的任意位置。在这种情况下,你必须找到第一个&#34;洞&#34;在按键序列中。

这应该有效地完成工作:

public static int GetFirstUnusedKey<TValue>(SortedDictionary<int, TValue> dict)
{
    if (dict.Comparer != Comparer<int>.Default)
        throw new NotSupportedException("Unsupported comparer");

    using (var enumerator = dict.GetEnumerator())
    {
        if (!enumerator.MoveNext())
            return 0;

        var nextKeyInSequence = enumerator.Current.Key + 1;

        if (nextKeyInSequence < 1)
            throw new InvalidOperationException("The dictionary contains keys less than 0");

        if (nextKeyInSequence != 1)
            return 0;

        while (enumerator.MoveNext())
        {
            var key = enumerator.Current.Key;
            if (key > nextKeyInSequence)
                return nextKeyInSequence;

            ++nextKeyInSequence;
        }

        return nextKeyInSequence;
    }
}

我添加了几项检查以确保前提条件有效。

答案 1 :(得分:2)

为什么不在键上进行二进制搜索?

您可以使用ElementAt()方法识别索引处的键值。如果键值大于索引,则在左子词典中搜索或选择右侧词典并继续,直到找到索引与索引值之间的第一个差异的索引。

答案 2 :(得分:0)

我并没有为这种方法申请任何表现奖杯,但我认为它在实现目标方面有所作为:

var sd = new SortedDictionary<int, object>();

sd.Add(1, 1);
sd.Add(2, 1);
sd.Add(4, 1);
sd.Add(5, 1);

var e = Enumerable.Range(1, 5).Except(sd.Keys).First();
在这种情况下,e = 3,如预期的那样。不过,我希望有更好的解决方案。

答案 3 :(得分:0)

请勿从0开始搜索未使用的密钥。

而是迭代使用过的键,从最低位开始(它们已排序)。

要么第一个是> 0,那么0是你未使用的最低值。

或两个键之间存在间隙,然后低于+ 1是您搜索的内容。