10

BCL 引入了一组不可变集合

我想知道ImmutableSortedSet和原生 FSharp有什么区别Set?似乎两者的性能特征相似。我还看到某处SortedSet被实现为红黑树,所以我猜ImmutableSortedSet也是这样。

fsharp 的内部实现是什么map?是此处声称的红黑树还是此处发现的AVL 树?

此外,为什么 MSDN 文档没有明确说明图书馆馆藏的实际数据结构是什么?我知道这些是实现细节并且即将改变。我的观点是,如果他们不想将库数据类型绑定到某种类型的众所周知的数据结构,他们至少应该提供所有方法性能特征的摘要,就复杂性而言?

4

2 回答 2

9

F# Set 和 Map 类型使用 AVL 树实现。

我不知道 MSDN 文档,您必须向 F# 团队询问 :)

无论如何,红黑树和 AVL 树的主要操作具有相同的计算复杂度。在实践中,它们具有不同的性能特征,可能会导致您为特定应用程序选择一种或另一种——红黑树具有更快的插入/删除速度,因为它们不需要对树进行尽可能多的重新平衡,而是检索由于它为插入/删除执行的额外平衡,在 AVL 树中更快。我想这就是为什么为 F# Map 和 Set 实现选择 AVL 树的原因—— Map/Set 通常创建一次(即不修改)然后重复查询。

https://en.wikipedia.org/wiki/Red%E2%80%93black_tree

https://en.wikipedia.org/wiki/AVL_tree

于 2013-04-25T13:50:33.677 回答
6

我想知道 ImmutableSortedSet 和原生 FSharp Set 有什么区别?

它们通常非常相似。主要区别在于 F#Set支持快速集理论运算(并、交和差)。

这是一个简单的 F# 程序,用于测量一些常见操作的性能:

open System.Collections.Immutable

while true do
  do
    let timer = System.Diagnostics.Stopwatch.StartNew()
    let cmp = LanguagePrimitives.FastGenericComparer<int>
    let mutable s1 = ImmutableSortedSet.Create<int>(cmp)
    let mutable s2 = ImmutableSortedSet.Create<int>(cmp)
    for i in 1..1000000 do
      s1 <- s1.Add i
    for i in 1000000..2000000 do
      s2 <- s2.Add i
    printfn "BCL ImmutableSortedSet: add in %fs" timer.Elapsed.TotalSeconds
    timer.Restart()
    for _ in 1..10 do
      for i in 1..1000000 do
        ignore(s1.Contains i)
    printfn "BCL ImmutableSortedSet: contains in %fs" timer.Elapsed.TotalSeconds
    timer.Restart()
    let s = s1.Union s2
    printfn "BCL ImmutableSortedSet: union in %fs" timer.Elapsed.TotalSeconds

  do
    let timer = System.Diagnostics.Stopwatch.StartNew()
    let mutable s1 = Set.empty
    let mutable s2 = Set.empty
    for i in 1..1000000 do
      s1 <- s1.Add i
    for i in 1000000..2000000 do
      s2 <- s2.Add i
    printfn "F# Set: %fs" timer.Elapsed.TotalSeconds
    timer.Restart()
    for _ in 1..10 do
      for i in 1..1000000 do
        ignore(s1.Contains i)
    printfn "F# Set: contains in %fs" timer.Elapsed.TotalSeconds
    timer.Restart()
    let s = Set.union s1 s2
    printfn "F# Set: union in %fs" timer.Elapsed.TotalSeconds

在我的机器上,我得到:

         BCL ImmutableSortedSet  F# Set
add                2.6s          3.0s
contains           2.1s          1.9s
union              1.1s          0.00004s

因此,F#Set的构建速度稍慢,搜索速度稍快,但对于集合论并集运算来说要快几个数量级。

fsharp map的内部实现是什么?是此处声称的红黑树还是此处发现的 AVL 树?

正如您的两个链接所述,F# 使用 AVL 树。

这实际上与上述性能数据有关。AVL 树包含每个分支中子树的最大高度,因此允许重新平衡子树而无需检查整个子树。相比之下,红黑树在每个分支中都包含一位数据,因此重新平衡子树需要遍历整个树,这会逐渐变慢。用外行的话来说,两个相同大小的非重叠集合的并集只需要创建一个包含两个现有树的新分支。请注意,UnionBCL API 中的 甚至无法表达这一点:它处理的是抽象IEnumerable而不是具体的集合。

此外,为什么 MSDN 文档没有明确说明图书馆馆藏的实际数据结构是什么?我知道这些是实现细节并且即将改变。我的观点是,如果他们不想将库数据类型绑定到某种类型的众所周知的数据结构,他们至少应该提供所有方法性能特征的摘要,就复杂性而言?

我同意文档中的复杂性会很好。

于 2013-12-22T01:03:15.017 回答