关于F#中可用的数据结构 是否有任何"官方"实现disjoint set data structures类似Union find的实现?
我在谷歌找到的只是这个片段:
Weighted Quick-Union with Path Compression
请注意,我是F#的初学者,也是编程的初学者 什么是有效的替代品?
答案 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定义了equate
和canonize
。
在notes的F#翻译中,他们仍然是equate
和canonize
。
翻译期间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))|]