目前,对于一项任务,我正在研究一个方案问题,我们使用方案列表来表示图形。我们使用的第一个变体是表示为
的边列表图'((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.
答案 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?)))