简体   繁体   English

绘制所有子节点公共Lisp的图

[英]Graph all child nodes common lisp

I need to find all nodes that are children of selected node. 我需要找到所有选定节点的子节点。 Graph is created like this: (setq graf1 '((A(BC)) (B(DE)) (C (FG )) (D (H)) (E(I)) (F(J)) (G(J)) (H()) (I(J)) (J()))) So, all children from node B are (on first level) D,E, on 2nd H,I, third J. Here's the code for finding first level children, but as i'm begineer in lisp i cant make it work for other ones. 像这样创建图形:(setq graf1'(((A(BC))(B(DE))(C(FG))(D(H))(E(I))(F(J))(G( J))(H())(I(J))(J())))因此,来自节点B的所有子代(在第一层上)是D,E,在第二个H,I上是第三个J。这是代码寻找一级孩子,但由于我是初学者,所以我无法使其适用于其他孩子。

(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())))

As I read it, the graph is a directed graph. 在我阅读时,该图是有向图。 So to find the children (directed edges) of the graph (in the example), 因此,要找到图的子项(有向边)(在示例中),

(defun children (node graph) (second (assoc node graph)))

then 然后

(children 'b graf1) ; with graf1 from the OP

returns (DE). 返回(DE)。 All you have to do then is to loop over the children, something like (very quick and dirty) 然后,您需要做的就是遍历孩子,就像(非常快又脏)

(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))))))

This returns (JIHDE) as children of B. 返回(JIHDE)作为B的子代。

Using alexandria package: 使用alexandria包:

(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)

I believe, this is what you wanted to do. 我相信,这就是您想要做的。 This will work for acyclic graphs, but it will recur "forever", if you have a cycle in it. 这将适用于非循环图,但如果其中包含循环,它将“永远”重复出现。 If you wanted to add depth counter, you could add it as one more argument to descendants or in the last mapcan transform the resulting list by inserting the depth counter. 如果要添加深度计数器,则可以将其作为descendants另一个参数添加,或者在最后一个mapcan中可以通过插入深度计数器mapcan转换结果列表。

With depth included: 包括深度:

(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))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM