File: union-find-container.lisp

package info (click to toggle)
cl-containers 20170403-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 1,072 kB
  • ctags: 1,387
  • sloc: lisp: 8,341; makefile: 14
file content (73 lines) | stat: -rw-r--r-- 1,768 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
(in-package #:containers)

;;; Simple union-find data structure

(defclass* union-find-node (parent-node-mixin container-node-mixin)
  ((rank 0 ir)))


(defmethod initialize-instance :after ((object union-find-node) &key) 
  ;; how kinky
  (setf (parent object) object))


(defmethod print-object ((o union-find-node) stream) 
  (print-unreadable-object (o stream :type nil :identity t)
    (format stream "UFN: ~A, ~D" (element o) (rank o))))


(defmethod make-set (item) 
  (make-instance 'union-find-node :element item))


(defmethod graft-nodes (node1 node2)
  (link-nodes (find-set node1) (find-set node2)))


(defmethod find-set (item)
  (if (eq (parent item) item)
    item
    (setf (parent item) (find-set (parent item)))))


(defmethod link-nodes (node1 node2)
  (if (> (rank node1) (rank node2))
    (setf (parent node2) node1)
    (progn (setf (parent node1) node2)
           (when (= (rank node1) (rank node2))
             (incf (slot-value node2 'rank))))))

;;; union find

(defclass* union-find-container (contents-as-hashtable-mixin)
  ())


(defmethod insert-item ((container union-find-container) item)
  (setf (item-at-1 (contents container) item) 
        (make-instance 'union-find-node :element item))
  item)


(defmethod representative ((container union-find-container) item)
  (element (representative-node container item)))


(defmethod representative-node ((container union-find-container) item)
  (find-set (item-at-1 (contents container) item)))


#+Test 
(let ((a (make-set 'a)) (b (make-set 'b))
      (c (make-set 'c)) (d (make-set 'd))
      (e (make-set 'e)) (f (make-set 'f))
      (g (make-set 'g)))
  
  (graft-nodes g c)
  (graft-nodes f e)
  (graft-nodes e d)
  (graft-nodes d c)
  (graft-nodes c b)
  (graft-nodes b a)
  f)