【问题标题】:Why is SortedDictionary<K, V>.GetEnumerator O(log n) but SortedSet<T>.GetEnumerator O(1)?为什么 SortedDictionary<K, V>.GetEnumerator O(log n) 而 SortedSet<T>.GetEnumerator O(1)?
【发布时间】:2014-09-07 00:04:48
【问题描述】:

来自SortedSet&lt;T&gt;.GetEnumerator 文档:

这个方法是一个O(1)操作

来自SortedDictionary&lt;K, V&gt;.GetEnumerator 文档:

此方法是 O(log n) 运算,其中 n 为计数。

考虑到SortedDictionary&lt;K, V&gt; 在内部实现为SortedSet&lt;KeyValuePair&lt;K, V&gt;,这两种说法是否都成立?我检查了SortedDictionary 类的GetEnumerator 代码——它直接使用SortedSet 的枚举器。我注意到SortedSet 的枚举器实现,在我看来它确实具有 O(log n) 特性(这里是代码):

public SortedSet<T>.Enumerator GetEnumerator()
{
  return new SortedSet<T>.Enumerator(this);
}

//which calls this constructor:
internal Enumerator(SortedSet<T> set)
{
  this.tree = set;
  this.tree.VersionCheck();
  this.version = this.tree.version;
  this.stack = new Stack<SortedSet<T>.Node>(2 * SortedSet<T>.log2(set.Count + 1));
  this.current = (SortedSet<T>.Node) null;
  this.reverse = false;
  this.siInfo = (SerializationInfo) null;
  this.Intialize();
}

private void Intialize()
{
  this.current = (SortedSet<T>.Node) null;
  SortedSet<T>.Node node1 = this.tree.root;
  while (node1 != null)
  {
    SortedSet<T>.Node node2 = this.reverse ? node1.Right : node1.Left;
    SortedSet<T>.Node node3 = this.reverse ? node1.Left : node1.Right;
    if (this.tree.IsWithinRange(node1.Item))
    {
      this.stack.Push(node1);
      node1 = node2;
    }
    else
      node1 = node2 == null || !this.tree.IsWithinRange(node2.Item) ? node3 : node2;
  }
}

这是否意味着文档有误,SortedSet&lt;T&gt;.GetEnumerator 是 O(log n)? 没有太多关于 GetEnumerator 调用的性能,只是确保我是否理解正确。

【问题讨论】:

  • 嗯,这看起来肯定是一个文档错误。
  • 您需要检查 SortedDictionary 的代码以了解发生了什么。它会调用 SortedSet log(n) 次吗?如果是这样,文档是正确的。
  • @user2880486 SortedDictionary 直接调用 SortedSet 枚举器。由于在内部它被实现为SortedSet&lt;KeyValuePair&lt;K,V&gt;&gt;。不,它不会调用枚举器日志 n 次。此外,我的问题不是SortedDictionary 为O logn,而是SortedSet 为O 1。这就是为什么我只发布了SortedSet 的枚举器代码。从代码中看起来不是 O 1 而是 O logn。
  • 感谢 MSDN 上有关我们主题的反馈。我已经修复了我们latest version of the documentation 中的文档错误。不幸的是,我无法修复同一主题的 4.0 版本。

标签: .net big-o asymptotic-complexity sortedset sorteddictionary


【解决方案1】:

我完全同意你的看法。

SortedSet内部使用了红黑树结构,保证平衡(Wikipedia;Red-Black Trees, R. Sedgewick, Princeton University)。
因此高度受限于2 * log2(n + 1)。甚至 SortedSet.cs 中的 code comment 也指出了这一点,并且相应地设置了枚举数堆栈的大小。

准备堆栈的 while 循环在初始化和处理 (MoveNext) 枚举器时都是 O(log n)。

在MSDN documentation 上对提交的此讨论进行反馈。

更新:

到今天,微软终于更新了文档。对于 4.0 版本,它仍然声明它是 O(1) 操作。尽管我对此表示怀疑,但我可以把它留在那里。

【讨论】:

  • 到今天微软终于更新了文档。对于 4.0 版本,它仍然声明它是 O(1) 操作。尽管我对此表示怀疑,但我可以把它留在那里。
猜你喜欢
  • 2012-04-08
  • 1970-01-01
  • 2021-08-25
  • 2014-01-09
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
  • 2020-07-09
  • 2020-10-24
相关资源
最近更新 更多