方案 - 使用列表列表

时间:2018-02-12 02:30:25

标签: scheme racket

目前,对于一项任务,我正在研究一个方案问题,我们使用方案列表来表示图形。我们使用的第一个变体是表示为

的边列表图
'((x y) (y z) (x z))

我们使用的图表的第二个变体被称为x-图表,表示为

((x (y z)) (y (z)) (z ()))

我们的任务是编写两个程序,从每个表单转换到另一个表单,我对如何解决这个问题感到茫然。我理解公式的一般概念,抓住一个节点并构建一个列表或基于边缘解构,但我不知道如何在你继续构建列表时。寻找一些指导而非答案。

我会在这里发布这个问题,只是为了进一步澄清,如果我没有充分描述它。

考虑将图表表示为Scheme列表的两种技术。我们可以将有向图表示为边缘列表。我们称这种表示为el-graph(即边缘列表图)。边缘本身是长度为2的列表,使得第一个元素是表示边缘源的符号,第二个元素是表示边缘目标的符号。请注意,边是一个列表(不只是一对)。例如,以下是图表:'((x y)(y z)(x z))。我们还可以表示类似于邻接矩阵的图。我们称这种表示为x图(即矩阵图)。在这种情况下,图是邻接列表,其中邻接是长度为2的列表,使得第一元素是节点(符号)而第二元素是该节点的目标列表。例如,以下是图表:'((x(y z))(y(z))(z()))。

Write function (el-graph->x-graph g), that accepts an el-graph g and returns an x-graph of g.
Write function (x-graph->el-graph g), that accepts an x-graph g and returns an el-graph of g.

1 个答案:

答案 0 :(得分:2)

下面的代码片段是实际的答案,但我尽力解释正在做什么,这样你可以忽略代码并编写自己的东西,如果你愿意的话。

从x-graph转换为edge-list图表非常简单。考虑一下您的示例:((x (y z)) (y (z)) (z ()))。当您进入第一个子列表时,您想要生成((x y) (x z));当你进入第二个子列表时,你想要生成((y z));当你进入第三个子列表时,你想要生成()。然后使用append-map将所有结果平面映射到一个列表中。

(define (x-graph->el-graph g)
  (append-map (lambda (sublist)
                (define from-node (car sublist))
                (define to-nodes (cadr sublist))
                (map (lambda (to-node)
                       (list from-node to-node))
                     to-nodes))
              g))

从边缘列表图到x图可能最容易使用group-by通过起始节点对边进行分组,然后收集每个组中的节点。但是,这不会给你空的z关联(我会把它作为练习留给你)。

(define (el-graph->x-graph g)
  (map (lambda (group)
         (list (caar group) (map cadr group)))
       (group-by car g eq?)))