Set data structures
Need to satisfy set operations union, intersection, is-elem? , adjoin
Different representations possible:
- Unordered lists - extremely inefficient
is-elem?andadjoinareand the others are because you end up traversing the whole list each time you want to check if an element is already present - possible to speed up
uniontoand adjointoby allowing repeated elements, but this comes at a cost of a lot of unnecessary memory usage and potentially increased complexity for is-elem?andintersection
- possible to speed up
- Ordered lists - better but needs a way to order the elements, trivial for numerical but other possibilities include lexicographic, cryptographic (eg. hashing) etc
is-elem?andadjoinare, essentially still as bad unionandintersectionare sped up tobecause the lists are reduced in size by at least 1 in each step
(define (intersection-set set1 set2)
(if (or (null? set1) (null? set2))
'()
(let ((x1 (car set1)) (x2 (car set2)))
(cond ((= x1 x2)
(cons x1
(intersection-set (cdr set1)
(cdr set2))))
((< x1 x2)
(intersection-set (cdr set1) set2))
((< x2 x1)
(intersection-set set1 (cdr set2)))))))
- Binary trees - even more efficient, given that the tree is “balanced”.
element-of-set?reduced tobecause searching through the tree can be done efficiently adjoinalsobecause it reduces to essentially the same search problem intersectionandunioncan still be done inbecause we can just reuse the ordered list implementation. This is possible because tree->listandlist->treecan be implemented withcomplexity so that overall complexity remains the same
(define (tree->list tree)
(define (copy-to-list tree result-list)
(if (null? tree)
result-list
(copy-to-list (left-branch tree)
(cons (entry tree)
(copy-to-list (right-branch tree)
result-list)))))
(copy-to-list tree '()))
(define (list->tree elements)
(car (partial-tree elements (length elements))))
(define (partial-tree elms n)
(if (= n 0)
(cons '() elms)
(let ((left-size (quotient (- n 1) 2)))
(let ((left-result (partial-tree elms left-size)))
(let ((left-tree (car left-result))
(non-left-elms (cdr left-result))
(right-size (- n (+ left-size 1))))
(let ((this-entry (car non-left-elms))
(right-result (partial-tree (cdr non-left-elms)
right-size)))
(let ((right-tree (car right-result))
(remaining-elms (cdr right-result)))
(cons (make-tree this-entry left-tree right-tree)
remaining-elms))))))))