Graph 用公共lisp绘制所有子节点

Graph 用公共lisp绘制所有子节点,graph,common-lisp,Graph,Common Lisp,我需要找到作为所选节点的子节点的所有节点。图形是这样创建的: (setq-graf1’((A(B-C))(B(D-E))(C(F-G))(D(H))(E(I))(F(J))(G(J))(H()(I(J))(J()) 所以,节点B的所有子节点都是(在第一级)D,E,在第二级H,I,第三级J。 下面是查找一级儿童的代码,但由于我在lisp中比较生僻,我无法使它适用于其他儿童 (defun sledG (cvor graf obradjeni) (cond ((null graf) '())

我需要找到作为所选节点的子节点的所有节点。图形是这样创建的: (setq-graf1’((A(B-C))(B(D-E))(C(F-G))(D(H))(E(I))(F(J))(G(J))(H()(I(J))(J()) 所以,节点B的所有子节点都是(在第一级)D,E,在第二级H,I,第三级J。 下面是查找一级儿童的代码,但由于我在lisp中比较生僻,我无法使它适用于其他儿童

(defun sledG (cvor graf obradjeni)
  (cond ((null graf) '())
        ((equal (caar graf) cvor)
                (dodaj (cadar graf) obradjeni))
        (t(sledG cvor (cdr graf) obradjeni)))
(defun dodaj (potomci obradjeni)
  (cond ((null potomci) '())
        ((member (car potomci) obradjeni)
         (dodaj (cdr potomci) obradjeni )
        (t(cons (car potomci)
                (dodaj (cdr potomci) obradjeni) ))))
(setq graf1 '((A(B C)) (B(D E)) (C (F G )) (D (H)) (E(I)) (F(J)) (G(J)) (H()) (I(J)) (J())))

正如我读到的,这个图是一个有向图。因此,要找到图(在示例中)的子对象(有向边)

然后

返回(D E)。然后你所要做的就是绕着孩子们转一圈,比如(很快又脏)


它返回(J I H D E)作为B的子图。

当我阅读它时,该图是一个有向图。因此,要找到图(在示例中)的子对象(有向边)

然后

返回(D E)。然后你所要做的就是绕着孩子们转一圈,比如(很快又脏)

这将使用包返回(J I H D E)作为B的子项。

我相信,这就是你想要做的。这将适用于非循环图,但如果有一个循环,它将“永远”重复出现。如果要添加深度计数器,可以将其作为另一个参数添加到
子体
,或者在最后一个
mapcan
中,通过插入深度计数器来转换结果列表

深度包括:

(defun descendants (tree label)
  (labels ((%descendants (depth label)
             (let ((generation
                    (mapcan #'cadr
                            (remove-if-not
                             (alexandria:compose
                               (alexandria:curry #'eql label) #'car)
                             tree))))
               (append (mapcar (alexandria:compose
                                #'nreverse
                                (alexandria:curry #'list depth))
                               generation)
                       (mapcan (alexandria:curry #'%descendants (1+ depth))
                               generation)))))
    (%descendants 0 label)))

;; ((D 0) (E 0) (H 1) (I 1) (J 2))
使用软件包:

我相信,这就是你想要做的。这将适用于非循环图,但如果有一个循环,它将“永远”重复出现。如果要添加深度计数器,可以将其作为另一个参数添加到
子体
,或者在最后一个
mapcan
中,通过插入深度计数器来转换结果列表

深度包括:

(defun descendants (tree label)
  (labels ((%descendants (depth label)
             (let ((generation
                    (mapcan #'cadr
                            (remove-if-not
                             (alexandria:compose
                               (alexandria:curry #'eql label) #'car)
                             tree))))
               (append (mapcar (alexandria:compose
                                #'nreverse
                                (alexandria:curry #'list depth))
                               generation)
                       (mapcan (alexandria:curry #'%descendants (1+ depth))
                               generation)))))
    (%descendants 0 label)))

;; ((D 0) (E 0) (H 1) (I 1) (J 2))

每个节点都由一个leter表示。节点及其子节点(也是节点)之间的连接以这种方式表示(节点(child1 child2…)示例(A(B C))-因此这里A处于car位置,是的,childer是cdr指向的子图-例如节点B和C的子节点。这是lisp学习练习的一部分。这是我收到的图形格式,不能以任何其他形式输入。最后,我应该打印所有节点的列表,这些节点都是一个选定节点的子节点,以及与该节点的距离exfob:(d1e1h2e2j3)。每个节点都由一个leter表示。节点及其子节点(也是节点)之间的连接以这种方式表示(节点(child1 child2…)示例(A(B C))-因此这里A处于car位置,是的,childer是cdr指向的子图-例如节点B和C的子节点。这是lisp学习练习的一部分。这是我收到的图形格式,不能以任何其他形式输入。最后,我应该打印作为一个选定节点的子节点的所有节点的列表以及与该节点的距离exfob:(d1e1h2e2j3)。谢谢,还有一个问题:使用这种方法,是否可以在节点后打印深度(与选定节点的距离)?例如,它将是(j3i2h2d1e1)我的一个想法是,孩子们返回,例如:((de1),然后我可以在c中为(carx)做循环(这将是(dee)](所有的孩子[不确定放在这里什么]图),或者,也许最好是((j3)(i2)(h2)(d1)(e1))因此,我可以使用remove-duplicates轻松删除重复项。谢谢,还有一个问题:使用这种方法,是否可以在节点后打印深度(与所选节点的距离)?例如,它将是(j3i2h2d1e1),我的一个想法是孩子们返回,例如:((de1),然后我可以在c中为(carx)[将是(dee)]做循环,附加(所有孩子[不确定放在这里什么]图)或者,也许最好是((j3)(i2)(h2)(d1)(e1)),这样我可以使用remove duplicates轻松地删除重复项。
(defun all-children (node graph)
  (let ((c (children node graph)))
    (if (null c) nil
        (union c (loop for x in c appending (all-children x graph))))))
(defvar *graf*
  '((a (b c)) (b (d e)) (c (f g)) (d (h)) (e (i)) (f (j)) (g (j)) (h nil) (i (j)) (j nil)))

(defun descendants (tree label)
  (let ((generation
         (mapcan #'cadr
                 (remove-if-not
                  (alexandria:compose (alexandria:curry #'eql label) #'car)
                  tree))))
    (append generation (mapcan (alexandria:curry #'descendants tree) generation))))

;; (D E H I J)
(defun descendants (tree label)
  (labels ((%descendants (depth label)
             (let ((generation
                    (mapcan #'cadr
                            (remove-if-not
                             (alexandria:compose
                               (alexandria:curry #'eql label) #'car)
                             tree))))
               (append (mapcar (alexandria:compose
                                #'nreverse
                                (alexandria:curry #'list depth))
                               generation)
                       (mapcan (alexandria:curry #'%descendants (1+ depth))
                               generation)))))
    (%descendants 0 label)))

;; ((D 0) (E 0) (H 1) (I 1) (J 2))