C# 什么';'ImmutableSortedSet'和fsharp'Set'之间的区别是什么?

C# 什么';'ImmutableSortedSet'和fsharp'Set'之间的区别是什么?,c#,.net,data-structures,f#,binary-search-tree,C#,.net,Data Structures,F#,Binary Search Tree,我想知道ImmutableSortedSet和本机FSharpSet之间有什么区别?似乎两者的性能特征是相似的。我还看到,SortedSet被实现为一个红黑树,所以我猜ImmutableSortedSet也是这样做的 fsharpmap的内部实现是什么?是这里声称的还是这里发现的 此外,为什么MSDN文档没有明确说明库集合的实际数据结构?我知道这些是实施细节,即将改变。我的观点是,如果他们不想将库数据类型绑定到某一类型的已知数据结构,那么他们至少应该提供所有方法性能特征的摘要,以复杂性衡量?F#

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

fsharp
map
的内部实现是什么?是这里声称的还是这里发现的

此外,为什么MSDN文档没有明确说明库集合的实际数据结构?我知道这些是实施细节,即将改变。我的观点是,如果他们不想将库数据类型绑定到某一类型的已知数据结构,那么他们至少应该提供所有方法性能特征的摘要,以复杂性衡量?

F#Set和Map类型是用AVL树实现的

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


在任何情况下,红黑树和AVL树的主要操作具有相同的计算复杂性。实际上,它们具有不同的性能特征,这可能会导致您为特定的应用程序选择其中一种——红黑树的插入/删除速度更快,因为它们不需要对树进行太多的重新平衡,但由于它对插入/删除执行了额外的平衡,因此在AVL树中检索速度更快。我想这就是为什么选择AVL树作为F#映射和集合实现的原因——映射/集合通常创建一次(即不修改),然后重复查询

我想知道ImmutableSortedSet和本机FSharp集之间的区别是什么

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

下面是一个简单的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
因此,F#
集合
的构造速度稍慢,搜索速度稍快,但集合论并集运算的速度要快几个数量级

fsharp map的内部实现是什么?这里是红黑树还是AVL树

当两个链接都处于状态时,F#使用AVL树

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

此外,为什么MSDN文档没有明确说明库集合的实际数据结构?我知道这些是实施细节,即将改变。我的观点是,如果他们不想将库数据类型绑定到某一类型的已知数据结构,那么他们至少应该提供所有方法性能特征的摘要(从复杂性的角度)


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

“我想这就是为什么选择AVL树作为F#Map和Set实现的原因。”我认为同样的原因也应该适用于BCL中的不可变集合。
         BCL ImmutableSortedSet  F# Set
add                2.6s          3.0s
contains           2.1s          1.9s
union              1.1s          0.00004s