图表所有子节点常见的lisp

时间:2013-03-27 00:40:28

标签: graph common-lisp

我需要找到所选节点的子节点。图形创建如下: (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. 这是找到第一级孩子的代码,但是因为我是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())))

2 个答案:

答案 0 :(得分:2)

在我阅读时,图表是有向图。因此,要找到图形的子项(有向边)(在示例中),

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

然后

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

返回(D E)。那么你所要做的就是绕过孩子,就像(非常快速和肮脏)

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

这将返回(J I H D E)作为B的孩子。

答案 1 :(得分:2)

使用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)

我相信,这就是你想要做的。这将适用于非循环图,但如果你有一个循环,它将“永远”重复。如果您想添加深度计数器,可以通过插入深度计数器将其作为descendants的另一个参数或最后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))