【问题标题】:What's the most-used data structure in OCaml to represent a Graph?OCaml 中最常用来表示 Graph 的数据结构是什么?
【发布时间】:2014-02-27 11:37:05
【问题描述】:

在 Java 或其他命令式编程中,图可以表示为 matrixadjacent listadjacent list 可能是最受欢迎的,因为它使用 array 时既紧凑又方便。

在函数式编程中,我们通常不使用mutable array。那么通常我们如何在 OCaml 或其他函数式编程中呈现图呢?

将数组替换为map?


ocaml 99, graph中列出了4种方式:

边缘子句形式

一种方法是列出所有边,边是一对节点。在这种形式中,对面描绘的图形表示为以下表达式:

['h', 'g';  'k', 'f';  'f', 'b';  'f', 'c';  'c', 'b']

我们称之为边子句形式。显然,孤立的节点是无法表示的。

图形术语形式

另一种方法是将整个图形表示为一个数据对象。根据图定义为一对两个集合(节点和边),我们可以使用以下 OCaml 类型:

type 'a graph_term = { nodes : 'a list;  edges : ('a * 'a) list }

那么,上面的示例图表示为:

let example_graph =
{ nodes = ['b'; 'c'; 'd'; 'f'; 'g'; 'h'; 'k'];
  edges = ['h', 'g';  'k', 'f';  'f', 'b';  'f', 'c';  'c', 'b'] }

我们称之为图词形式。请注意,列表保持排序,它们实际上是集合,没有重复的元素。每条边在边列表中只出现一次;即从节点 x 到另一个节点 y 的边表示为 (x,y),不存在对 (y,x)。 graph-term 形式是我们的默认表示形式。您可能希望使用集合而不是列表来定义类似的类型。

邻接列表形式

第三种表示方法是将与该节点相邻的节点集与每个节点相关联。我们称之为邻接表形式。

人性化的形式

到目前为止,我们介绍的表示非常适合自动化处理,但它们的语法对用户不太友好。手动输入术语既麻烦又容易出错。我们可以定义一个更紧凑和“对人类友好”的符号如下:一个图(带有 char 标记的节点)由一串原子和 X-Y 类型的术语表示。原子代表孤立节点,X-Y 术语描述边缘。如果 X 显示为边的端点,则会自动将其定义为节点。我们的例子可以写成:

"b-c f-c g-h d f-b k-f h-g"

考虑到处理效率,我认为以上 4 种方式都不够好。

对于record type graph-term form,没有有效的方法来定位节点(总是O(n))并定位连接到节点的边。

【问题讨论】:

  • 您的意思是“代表”吗?因为,仅仅呈现一个图表,我会使用类似 graphviz ....
  • @Ingo 对不起,是的,代表
  • @JacksonTale 在我们的系统发育应用程序中,在我们使用邻接列表形式的树和图上。节点是它们与邻居(叶子或内部或网状)节点类型的键的映射——参见 poy5 项目中的 tree.ml。

标签: functional-programming ocaml


【解决方案1】:

您可能会对 OCamlGraph 库 (http://ocamlgraph.lri.fr) 感兴趣,它提供了各种图的实现,无论是持久的还是可变的,以及一堆经典算法。

【讨论】:

    【解决方案2】:

    有两件事需要考虑:图的表示,以及一些图算法中使用的中间数据结构。

    我认为邻接表形式是表示图的最节省内存的方式。可以通过拥有该类型的树或地图来稍微改进

    type Graph a = Map a [a]
    

    但是当你想运行一些算法,比如“强连通分量”或“拓扑排序”,那么这些算法很可能会使用可变数组来实现它。

    请注意,在 Haskell 等语言中,与全局状态相反,ST monad 可以具有临时可变状态(即数组)。使用它的函数总体上仍然是纯的。

    【讨论】:

    • @JacksonTale 确实不是,我想可能是(a * a list) map 之类的(我不知道他们为什么在 ML 中倒写类型)
    • @JacksonTale 它看起来确实像 Haskell。 OCaml 等价物类似于A.t list AMap.t,其中A 是实现Map.OrderedTypeAMap.t = Map.Make(A) 的模块(尽管最好使用Set 而不是列表
    【解决方案3】:

    在命令式语言中,图形表示的选择取决于您要解决的问题。

    函数式语言也是如此。

    Ocamlgraph 提供了足够的抽象,您可以编写一个独立于底层图形表示的算法,当然算法的运行时间仍然取决于实现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 1970-01-01
      • 1970-01-01
      • 2010-10-07
      相关资源
      最近更新 更多