3.18 Exercise 3.18
Detecting cycles can be done simply. We can traverse the list and keep a
list of all the entries we’ve seen so far, and if we ever run into a node
that’s already in the list of things we’ve seen, then we know we have a cycle.
(define (detect-cycle l) | (define (update l seen) | (cond ((null? l) #f) | ((contains seen l) #t) | (else | (update (cdr l) (cons l seen))))) | (update l '())) |
|
One thing to notice about this procedure is that the seen list contains
references to entire lists, and not just the cars of the lists. This is
important: We really want to see if we pass by an entire list we’ve already
seen before, not just a value we’ve seen before. Otherwise, the list
’(1 2 1 2) would contain a cycle.
The contains procedure is mostly trivial. Notice how it compares
(car lst) to v – this is because every entry in the seen
list is in fact a list, and (car lst) gives us one of those lists.
(define (contains lst v) | (cond ((null? lst) #f) | ((eq? (car lst) v) #t) | (else | (contains (cdr lst) v)))) |
|