使用F#联盟查找

时间:2016-01-09 14:11:15

标签: data-structures f#

关于F#中可用的数据结构 是否有任何"官方"实现disjoint set data structures类似Union find的实现?

我在谷歌找到的只是这个片段:

Weighted Quick-Union with Path Compression

请注意,我是F#的初学者,也是编程的初学者 什么是有效的替代品?

2 个答案:

答案 0 :(得分:3)

F#数据结构

  

关于F#中可用的数据结构是否有任何“官方”   实现不相交的集合数据结构,如实现   联盟找到?

我不知道任何官方版本。

最着名的F#数据结构来源:

有一个F#PowerPack,它是一个有很多有用代码的文件,但它现在已被分解成部分。

查看Jack Fox's post以获取有关F#数据结构的信息。

对于特定于域的数据结构,请搜索F# community projects

特别适用于Union / Find:

Handbook of Practical Logic and Automated Reasoning lib.ml中的lib.fs John Harrison定义了equatecanonize

notes的F#翻译中,他们仍然是equatecanonize

翻译期间Disjoint-set data structure

请参阅:Topics in Automated Deduction - Lecture 5 - Page 4: Union/Find
请参阅:https://plnkr.co/edit/J0PeIlLsaASer4k8owdj?p=preview

union被称为equate find被称为canonize

  

什么是有效的替代方案?

我不知道John Harrison的代码是否更有效,因为我没有进行任何测试。我也不知道其他任何实现,但我知道该版本可以作为自动定理证明器的核心部分运行良好。

答案 1 :(得分:2)

我自己实施了它 它并不那么困难。我希望它没有错误

UnionFind.fs

// union find by rank with path compression

namespace UnionFind


// using array from 1..N 
// don't use .[0]

type Node = { Parent:int ; Rank:int}

type Partition (N:int) = 

    let nodearray =   [| for i in 0..N do yield {Parent = i; Rank = 0} |]

    let length = (Array.length nodearray) - 1

    member p.Item 
        with get(idx) = nodearray.[idx]

    member p.find (i) = 
        let mutable tmp0 = i
        let mutable tmp1 = p.[i].Parent
        while (tmp0 <> tmp1) do tmp0 <- tmp1
                                tmp1 <- p.[tmp1].Parent
        tmp0
    member p.find_compress (i) :int =
        let mutable tmp0 = i
        let mutable tmp1 = p.[i].Parent
        let rec one_step ok list =
            match ok with 
              | false -> list
              | true ->   tmp0 <- tmp1
                          tmp1 <- p.[tmp1].Parent
                          one_step (tmp0<>tmp1) (tmp0::list) 

        let list = one_step (tmp0<>tmp1) [i]  
        // ranks stay the same with find_compress
        list |> List.head |> (fun i ->  let r = nodearray.[i].Rank
                                        (nodearray.[i] <- {Parent = tmp0 ; Rank=r} ))
        list |> List.tail |> List.iter ( fun i -> let r = nodearray.[i].Rank
                                                  (nodearray.[i] <- {Parent = tmp0 ; Rank=r} ))

        tmp0

    member p.union_by_rank (i,j) : bool = // returns false if i and j hav the same parent, true otherwise
       if i=j then false else
          let x = p.find_compress(i)
          let y = p.find_compress(j)
          let rx = p.[x].Rank 
          let ry = p.[y].Rank

          if x=y then false else
             if (rx<ry) then nodearray.[x] <- {Parent = y; Rank = rx}                         
             if (ry<rx) then nodearray.[y] <- {Parent = x; Rank = ry}                
             if (rx=ry) then nodearray.[x] <- {Parent = y; Rank = ry}
                             nodearray.[y] <- {Parent = y; Rank = ry+1}
             true                             

    member p.print() = 
       printfn "%A" nodearray

    member p.output() = [|for i in 0..length do yield (i,p.find_compress(i))|]