Ocaml中定向图的合理数据结构类型

时间:2017-03-19 12:23:38

标签: data-structures graph ocaml graph-theory

我想使用邻接列表来表示图形结构,我不需要对边缘进行加权。 我想练习简单的练习,比如寻找一个循环,BFS,DFS,添加删除边缘......没什么特别的。 (我也可以用Hashtables做,但我需要更多List练习)

type 'a dgraph = DG of ('a * 'a list) list 

我的问题是:

  1. 这是DG的合理代表吗?
  2. 这些不应该是递归类型吗? (不知怎的感觉更自然)
  3. 我不想从头开始拍摄自己并从一开始就制作设计不佳的type,这将导致更复杂的实施。

    示例:

    let g = 
        DG (
            [
                ('a', ['c'; 'd']);
                ('c', ['d']);
                ('b', ['a'; 'e']);
            ]
        )
    

    注意:

    我没有在http://ocaml.org/learn/tutorials/99problems.html#Graphs找到邻接列表表示。

    enter image description here

1 个答案:

答案 0 :(得分:2)

这是图表的完美表示。您需要确保标签是唯一的。此外,标签和节点的其他可能内容之间没有区别。

使用此结构,从标签到带有标签的节点需要搜索外部列表。如果你的图表变大,这可能会花费太长时间。因此,您需要构建从标签到节点的辅助映射。我自己做了很多次。

另一种解决方案是使节点索引独立于节点内容。这也减少了处理重复标签的难度。我正在研究图形问题,结构基本上是这样的:

 type 'a mygraph = ('a * int list) array

'a类型表示节点的内容,数组索引用于将它们链接在一起。

我还使用了一个使用哈希表而不是数组的结构。如果节点类型中有一些可用作索引的唯一标识符,则此方法很有效。 (或者您可以使用任意构造的索引。)哈希表结构的优点是更容易修改图形。

看起来您的数据结构应该是递归的,但(在我看来)这会混合图形和图形的表示。如果您希望您的数据结构实际上图形而不仅仅是表示图形,那么它必须是递归的。像这样:

type 'a rgraph = RG of 'a * 'a rgraph list

这样的数据结构几乎不可能像OCaml这样的热切语言一起使用。在有周期时构造所需的值非常困难。

可以使用let rec

完成
# let rec rg1 = RG (17, [rg1]);;
val rg1 : int rgraph = RG (17, [<cycle>])

但是,我个人从未见过使用这样结构的“真实世界”代码。请注意,let rec的这种用法在OCaml手册中标记为语言扩展(第7.2节,值的递归定义)。

您可以通过使用引用使这样的数据结构更容易处理,这样的事情可能是:

type 'a rrgraph = RRG of 'a * 'a rrgraph list ref

然后您可以创建节点并在之后将它们链接在一起。我过去曾使用过这样的结构,但我觉得我失去了使用不可变数据的一些很好的保证。

# let node1 = RRG (7, ref []);;
val node1 : int rrgraph = RRG (7, {contents = []})
# let node2 = RRG (8, ref []);;
val node2 : int rrgraph = RRG (8, {contents = []})
# let RRG (_, links) = node1 in links := [node2];;
- : unit = ()
# let RRG (_, links) = node2 in links := [node1];;
- : unit = ()
# node1;;
- : int rrgraph = RRG (7, {contents = [RRG (8, {contents = [<cycle>]})]})

这样的表示的一个优点是您可以自由地创建新节点,而无需维护包含所有节点的中央表。垃圾收集器负责删除不再可访问的节点。