在.NET中实现的图形的访问列表的理想集合类型是什么?

时间:2016-10-11 09:50:15

标签: .net algorithm collections f#

根据Sedgewick的算法书,他使用Java中的 Bag 集合来实现Graphs的邻接列表。因为在O(1)中搜索并允许从顶点到另一个顶点的重复边缘,所以它非常有意义。 可以使用列表但是它们在搜索中比在O(n)中慢,所以我会避免它。

不幸的是,.NET没有它。有像Wintellect这样的实现,但它们不是Portable(或.NET标准兼容)。 我该怎么用?

1 个答案:

答案 0 :(得分:2)

经过一番思考后,我将自己的Bag实现为字典<'T,int> 这就像一个多重集或一个包。这是我在F#中的实现:

type Bag<'T when 'T : equality>() =
    let dict = Dictionary<'T,int>()
    let mutable count = 0

    member x.Add = (x:>ICollection<'T>).Add

    member x.Remove = (x:>ICollection<'T>).Remove

    member x.Count = (x:>ICollection<'T>).Count

    member x.Clear = (x:>ICollection<'T>).Clear

    member x.ItemCount item =
        match dict.TryGetValue item with
            | true, itemCount -> itemCount
            | _ -> 0

    interface ICollection<'T> with

        member x.Add item =
            count <- count + 1
            let itemCount =
                match dict.TryGetValue item with
               | true, itemCount -> itemCount
               | _ -> 0
            dict.[item] <- itemCount + 1

        member x.Clear() = dict.Clear()

        member x.Contains item = dict.ContainsKey item

        member x.CopyTo(array, arrayIndex) =
            x
            |> Seq.take(array.Length - arrayIndex)
            |> Seq.iteri (fun i item ->  array.[i + arrayIndex] <- item)

        member x.Count = count

        member x.GetEnumerator()  =
            (x :> ICollection<'T>).GetEnumerator() :> Collections.IEnumerator

        member x.GetEnumerator() =
            let seq =
                let innerSeq (kvp : KeyValuePair<'T,int>) =
                     Seq.init kvp.Value (fun _ -> kvp.Key)
                dict |> Seq.map innerSeq |> Seq.collect id
            seq.GetEnumerator()

        member x.IsReadOnly = false

        member x.Remove item =
            match dict.TryGetValue item with
            | true, 1 ->
                count <- count - 1
                dict.Remove item
            | true, itemCount ->
                count <- count - 1 
                dict.[item] <- itemCount - 1
                true
            | _ -> false