A node in a family tree includes both information about the children and the parents of a person:
mother father
------ ------
\ /
\ /
\ /
\ /
________
children
How can we create nodes that contain references from, say, mother, to its children and from each child back to mothers?
(define-struct person (name children mother father)) (define Eve (make-person 'Eve-I empty #f #f)) ;; at child birth: (make-person 'Abel empty Eve #f)but this does not update Eve.
;; create-child : sym person person -> person
;; Purpose: make a new person structure to represent name
;; Effect: add new person as child to mother and father
(define (create-child name mother father)
(local ((define new-child (make-person name empty mother father)))
(begin
(set-person-children! mother (cons new-child (person-children mother)))
(set-person-children! father (cons new-child (person-children father)))
new-child)))
Problem: Given a node N in a family tree. Wanted: is X a name of a
descendant or an ancestor of N.
Now use data definitions to specify children-oriented family trees and
parent-oriented family trees.
A descendant tree is either
* #f
* (make-person symbol (listof dt) p1 p2) where
dt is a descendant tree and p1, p2 are person
structures.
|
An ancestor tree is either
* #f
* (make-person symbol (listof p) at1 at2) where
at1, at2 are ancestor trees and p are person
structures.
|
;; descendants# : descendant-tree -> num
(define (descendants# dt)
(cond
((boolean? dt) 0)
(else (+ 1 (foldl + 0
(map descendants#
(person-descendants dt)))))))
|
;; ancestors# : ancestor-tree -> num
(define (ancestors# at)
(cond
((boolean? at) 0)
(else (+ 1 (ancestors# (person-father at))
(ancestors# (person-mother at))))))
|

(define A (create-node)) (define B (create-node)) ... (connect A to B) ...
How?
(define-struct node (stuff info reachables)) ;; A node is (make-node boolean #f (listof node)). (define (create-node) (make-node #f 'anything empty)) ;; connect : node node -> void ;; Effect: add b to the reachables of a (define (connect a to b) (set-node-reachables! a (cons b (node-reachables a)))) (define to 'to)
How do we find a route?
(define (find-route from to graph)
(cond
((eq? from to) (list to))
((node-stuff from) #f)
(else
(begin
(set-node-stuff! from #t)
(find-route/list (node-reachables from) to graph)))))
(define (find-route/list lo-from to graph)
(cond
((empty? lo-from) #f)
(else (local ((define from (first lo-froms))
(define route (find-route from to graph)))
(cond
((boolean? route) (find-route/list (rest lo-froms) to graph))
(else (cons from route)))))))
Clean up: the graph nodes remain modified after a traversal. That's no good. We need to make sure that the "stuff" thingies are set back to #f after we have figured out the route:
;; find-route : node node (listof node) -> (listof node)
;; Purpose: find a route from, to in graph
;; Effect: -
(define (find-route from to graph)
(local ((define (find-route ...) ...)
(define (find-route/list ...) ...)
(define the-route (find-route ...)))
(begin
(for-each (lambda (x) (set-node-stuff! x #f)) graph)
the-route)))
| Matthias Felleisen | This page was generated on Wed Apr 14 06:40:24 CDT 1999. |