代码之家  ›  专栏  ›  技术社区  ›  Chris Abbott

用公共Lisp表示有向无环图

  •  2
  • Chris Abbott  · 技术社区  · 6 年前

    通常,要在Lisp中表示基本的无向图,我可以创建父节点及其相应子节点的列表,如中所述 this question

    enter image description here

    此图生成边列表:

    (1 (2 6 7 8) 3 (4 (9 12)) 5 (10 11)) 
    

    enter image description here

    现在,节点8有多个父节点(2,3),但是当我们试图表示这一点时,我们无法判断节点8是否连接到两个父节点,或者是否有两个节点8:

    (1 (2 6 7 8) (3 8) (4 (9 12)) (5 10 11))
    

    对于具有唯一节点的图,我们当然可以做出这样的假设,但据我所知,DAG可以具有重复节点。。。那我们怎么处理呢?此外,如何在Lisp中将其表示为列表?

    2 回复  |  直到 6 年前
        1
  •  6
  •   sds Niraj Rajbhandari    6 年前

    表示DAG的正确方法是 (顶点):

    (defstruct node
      payload
      children)
    

    cons 而不是细胞。

    所给树的列表表示形式 合并 有效载荷 带着一个没有孩子的孩子 节点 把最右边的树枝弄乱了。 正确的表示是

    (1 (2 (6) (7) (8)) (3) (4 (9 (12))) (5 (10) (11)))
    

    现在,共享无子节点的DAG (8) 在孩子们之间 节点数 (2 ...) (3 ...) 应该只共享一个单元:

    (1 (2 (6) (7) #1=(8)) (3 #1#) (4 (9 (12))) (5 (10) (11)))
    

    看到了吗 #n= #n# 对于读者来说。 当然,你不应该用它们来 达格。

    下面是创建DAG的方法:

    (defun make-node (&key payload children)
      (cons payload children))
    (defparameter *my-dag*
      (let ((shared-mode (make-node :payload 8)))
        (make-node
         :payload 1
         :children
         (list (make-node :payload 2
                          :children (list (make-node :payload 6)
                                          (make-node :payload 7)
                                          shared-mode))
               (make-node :payload 3
                          :children (list shared-mode))
               (make-node :payload 4
                          :children (list (make-node :payload 9
                                                     :children (list (make-node :payload 12)))))
               (make-node :payload 5
                          :children (list (make-node :payload 10)
                                          (make-node :payload 11)))))))
    (setq *print-circle* t)
    *my-dag*
    ==> (1 (2 (6) (7) #1=(8)) (3 #1#) (4 (9 (12))) (5 (10) (11)))
    
        2
  •  2
  •   Rainer Joswig mmmmmm    6 年前

    只需列出具有两个节点ID的顶点:

    ((1 2) (1 3) (1 4) (1 5) (2 6) (2 7) (2 8) ... )
    

    或者使用向量:

    #((1 2) (1 3) (1 4) (1 5) (2 6) (2 7) (2 8) ... )
    

    或者使用节点及其后续节点的列表:

    ((1 2 3 4 5) (2 6 7 8) (3 8) (4 9) ...)