【发布时间】:2014-02-27 11:37:05
【问题描述】:
在 Java 或其他命令式编程中,图可以表示为 matrix 或 adjacent list。 adjacent 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