Functional programming 什么';OCaml中表示图形最常用的数据结构是什么?
在Java或其他命令式编程中,图形可以表示为Functional programming 什么';OCaml中表示图形最常用的数据结构是什么?,functional-programming,ocaml,Functional Programming,Ocaml,在Java或其他命令式编程中,图形可以表示为矩阵或相邻列表。相邻列表可能最受欢迎,因为它使用数组时紧凑方便 在函数式编程中,我们通常不使用可变数组。那么通常我们如何在OCaml或其他函数式编程中显示图形 将阵列替换为映射 其中列出了4种方法: 边缘条款格式 一种方法是列出所有边,边是一对节点。在这种形式中,对面描绘的图形表示为以下表达式: ['h', 'g'; 'k', 'f'; 'f', 'b'; 'f', 'c'; 'c', 'b'] 我们称之为边缘条款形式。显然,无法表示孤立的
矩阵
或相邻列表
。相邻列表
可能最受欢迎,因为它使用数组
时紧凑方便
在函数式编程中,我们通常不使用可变数组
。那么通常我们如何在OCaml或其他函数式编程中显示图形
将阵列替换为映射
其中列出了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'] }
我们称之为图项形式。注意,列表保持排序,它们实际上是集合,没有重复的元素。每个边在“边”列表中仅显示一次;i、 e.从一个节点x到另一个节点y的边表示为(x,y),耦合(y,x)不存在。图形术语形式是我们的默认表示形式。您可能希望使用集合而不是列表来定义类似的类型
邻接列表表格
第三种表示方法是将与该节点相邻的一组节点与每个节点相关联。我们称之为邻接列表形式
人性化形式
到目前为止,我们介绍的表示非常适合自动化处理,但它们的语法不是非常用户友好。手工输入术语既麻烦又容易出错。我们可以定义一个更紧凑和“人性化”的表示法如下:一个图(带有字符标记的节点)由一串原子和X-Y类型的项表示。原子代表孤立的节点,X-Y项描述边。如果X显示为边的端点,则会自动将其定义为节点。我们的示例可以写成:
"b-c f-c g-h d f-b k-f h-g"
考虑到处理效率,我认为以上4种方法都不够好
对于
记录类型图形术语表单
,没有有效的方法来定位节点(O(n)
始终)和定位附加到节点的边。需要考虑两件事:图形的表示和某些图形算法中使用的中间数据结构
我认为邻接列表形式是表示图的最有效的内存方式。可以通过使用这种类型的树或地图来进行一些改进
type Graph a = Map a [a]
但是,当您想要运行一些算法,如“强连接组件”或“拓扑排序”时,这些算法很可能会使用可变数组来实现它
注意,在Haskell这样的语言中,ST monad使临时可变状态(即数组)成为可能,而不是全局状态。使用此函数的函数总体上仍然是纯函数。您可能会对OCamlGraph库()感兴趣,它提供了各种图形的实现,无论是持久的还是可变的,以及一系列经典算法。在命令式语言中,图形表示法的选择将取决于您试图解决的问题 函数式语言也是如此
Ocamlgraph提供了足够的抽象,您可以编写独立于底层图形表示的算法,当然,算法的运行时间仍然取决于实现。您是说“表示”吗?因为,为了仅仅呈现一个图表,我会使用类似graphviz的东西…@Ingo对不起,是的,represent@JacksonTale在我们的系统发育应用程序中,我们在树和图上使用邻接列表形式。这些节点是它们的键与相邻节点(叶子、内部或网状)类型的映射——请参见poy5项目中的tree.ml。@JacksonTale确实不是,我认为它可能是
(a*a list)映射
或其他什么(我不知道它们为什么用ml反向编写类型)@JacksonTale它看起来确实像Haskell。OCaml等价物类似于A.t list AMap.t
,其中A
是一个实现Map.OrderedType
和AMap.t=Map.Make(A)
的模块(不过最好使用Set
,而不是直接列出我们在这里所做的事情:。