-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtsort.scm
More file actions
45 lines (44 loc) · 1.51 KB
/
tsort.scm
File metadata and controls
45 lines (44 loc) · 1.51 KB
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
;;; Topological sort with cycle detection:
;;
;; A functional implementation of the algorithm described in Cormen,
;; et al. (2009), Introduction to Algorithms (3rd ed.), pp. 612-615.
(define (topological-sort dag pred)
(define (alist-ref x al def)
(cond ((find (lambda (a) (pred x (car a))) al) => cdr)
(else def)))
(define (alist-update! x y al)
(cond ((find (lambda (a) (pred x (car a))) al) =>
(lambda (a)
(set-cdr! a y)
al))
(else (cons (cons x y) al))))
(define (visit dag node edges path state)
(case (alist-ref node (car state) #f)
((grey)
(error "cycle detected in topological sort" node (reverse path) dag))
((black)
state)
(else
(let walk ((edges (or edges (alist-ref node dag '())))
(state (cons (cons (cons node 'grey) (car state))
(cdr state))))
(if (null? edges)
(cons (alist-update! node 'black (car state))
(cons node (cdr state)))
(let ((edge (car edges)))
(walk (cdr edges)
(visit dag
edge
#f
(cons edge path)
state))))))))
(let loop ((dag dag)
(state (cons (list) (list))))
(if (null? dag)
(cdr state)
(loop (cdr dag)
(visit dag
(caar dag)
(cdar dag)
'()
state)))))