;;; This is sets.scm version 1.00 of 92/09/10. ;;; Sets implemented using bounded balanced binary trees. ;;; John D. Ramsdell --- The MITRE Corporation. ;;; The implementation is based on Binary search trees of Bounded ;;; Balance, similar to Nievergelt & Reingold, SIAM J. Computing ;;; 2(1), March 1973. ;;; Copyright 1992 by The MITRE Corporation. ;;; Permission to use, copy, modify, and distribute this software and ;;; its documentation for any purpose and without fee is hereby granted, ;;; provided that the above copyright notice appear in all copies. The ;;; MITRE Corporation makes no representations about the suitability of ;;; this software for any purpose. It is provided "as is" without express ;;; or implied warranty. ;;; This is a translation of Shephen Adams' SML programs used to ;;; implement sets of integers. ;;; Copyright 1992 Stephen Adams. ;;; ;;; This software may be used freely provided that: ;;; 1. This copyright notice is attached to any copy, derived work, ;;; or work including all or part of this software. ;;; 2. Any derived work must contain a prominent notice stating that ;;; it has been altered from the original. ;;; Name(s): Stephen Adams. ;;; Department, Institution: Electronics & Computer Science, ;;; University of Southampton ;;; Address: Electronics & Computer Science ;;; University of Southampton ;;; Southampton SO9 5NH ;;; Great Britian ;;; E-mail: sra@ecs.soton.ac.uk ;;; The application must define element-less?. ;;; Exports ;;; (empty? SET) => BOOLEAN ;;; (empty-set) => SET ;;; (adjoin ELEMENT SET) => SET ;;; (remove ELEMENT SET) => SET ;;; (singleton ELEMENT) => SET ;;; (element? ELEMENT SET) => BOOLEAN ;;; (union SET SET) => SET ;;; (intersection SET SET) => SET ;;; (set-difference SET SET) => SET ;;; (sum-sets LIST-of-SETS) => SET. ;;; (set->list SET) => LIST-of-ELEMENTS. ;;; (list->set LIST-of-ELEMENTS) => SET. (define (data tree) (vector-ref tree 0)) (define (size tree) (vector-ref tree 1)) (define (left tree) (vector-ref tree 2)) (define (right tree) (vector-ref tree 3)) (define the-empty-set (vector 'empty 0)) (define (mk-tree data left right) (vector data (+ 1 (size left) (size right)) left right)) ;;; Tree balancing. ;;; Rotations. ;;; a b ;;; / \ / \ ;;; x b ==> a z ;;; / \ / \ ;;; y z x y (define (single-left d l r) (mk-tree (data r) (mk-tree d l (left r)) (right r))) ;;; a b ;;; / \ / \ ;;; w c / \ ;;; / \ ==> a c ;;; b z / \ / \ ;;; / \ w x y z ;;; x y (define (double-left d l r) (let ((lr (left r))) (mk-tree (data lr) (mk-tree d l (left lr)) (mk-tree (data r) (right lr) (right r))))) ;;; (b (a x y) z)) ==> (a x (b y z)) (define (single-right d l r) (mk-tree (data l) (left l) (mk-tree d (right l) r))) ;;; (c (a w (b x y)) z) ==> (b (a w x) (c y z)) (define (double-right d l r) (let ((rl (right l))) (mk-tree (data rl) (mk-tree (data l) (left l) (left rl)) (mk-tree d (right rl) r)))) (define (balance d l r) (let ((sl (size l)) (sr (size r))) (cond ((< (+ sl sr) 2) (mk-tree d l r)) ((>= sr (* 3 sl)) ; Right too big. (if (< (size (left r)) (size (right r))) (single-left d l r) (double-left d l r))) ((>= sl (* 3 sr)) ; Left too big. (if (< (size (right l)) (size (left l))) (single-right d l r) (double-right d l r))) (else (mk-tree d l r))))) ;;; Exported (define (empty? s) (zero? (size s))) ;;; Exported ; (singleton e) == (mk-tree e the-empty-set the-empty-set) (define (singleton e) (vector e 1 the-empty-set the-empty-set)) ;;; Exported (define (element? e s) (cond ((empty? s) #f) ((element-less? e (data s)) (element? e (left s))) ((element-less? (data s) e) (element? e (right s))) (else #t))) (define (insert e s) (cond ((empty? s) (singleton e)) ((element-less? e (data s)) (balance (data s) (insert e (left s)) (right s))) ((element-less? (data s) e) (balance (data s) (left s) (insert e (right s)))) (else s))) (define (concat3 l d r) (cond ((empty? l) (insert d r)) ((empty? r) (insert d l)) ((< (* 3 (size l)) (size r)) ; Right too big. (balance (data r) (concat3 l d (left r)) (right r))) ((< (* 3 (size r)) (size l)) ; Left too big. (balance (data l) (left l) (concat3 (right l) d r))) (else (mk-tree d l r)))) (define (split< e s) (cond ((empty? s) s) ((element-less? e (data s)) (split< e (left s))) ((element-less? (data s) e) (concat3 (left s) (data s) (split< e (right s)))) (else (left s)))) (define (split> e s) (cond ((empty? s) s) ((element-less? (data s) e) (split> e (right s))) ((element-less? e (data s)) (concat3 (split> e (left s)) (data s) (right s))) (else (right s)))) ;;; Exported. ;;; This implementation assumes card(s0) is small. (define (union s0 s1) (cond ((empty? s0) s1) ((empty? s1) s0) (else (let ((d (data s0))) (concat3 (union (left s0) (split< d s1)) d (union (right s0) (split> d s1))))))) (define (delete e s) (cond ((empty? s) s) ((element-less? e (data s)) (balance (data s) (delete e (left s)) (right s))) ((element-less? (data s) e) (balance (data s) (left s) (delete e (right s)))) (else (merge (left s) (right s))))) (define (merge l r) (cond ((empty? l) r) ((empty? r) l) (else (balance (smallest r) l (delete-smallest r))))) (define (smallest s) (if (empty? (left s)) (data s) (smallest (left s)))) (define (delete-smallest s) (if (empty? (left s)) (right s) (balance (data s) (delete-smallest (left s)) (right s)))) ;;; Exported. ;;; This implementation assumes card(s1) is small. (define (set-difference s0 s1) (cond ((empty? s0) s0) ((empty? s1) s0) (else (let ((d (data s1))) (concat (set-difference (split< d s0) (left s1)) (set-difference (split> d s0) (right s1))))))) (define (concat l r) (cond ((empty? l) r) ((empty? r) l) ((< (* 3 (size l)) (size r)) ; Right too big. (balance (data r) (concat l (left r)) (right r))) ((< (* 3 (size r)) (size l)) ; Left too big. (balance (data l) (left l) (concat (right l) r))) (else (balance (smallest r) l (delete-smallest r))))) ;;; Exported (define (intersection s0 s1) (cond ((empty? s0) s0) ((empty? s1) s1) (else (let ((d (data s1))) (let ((l (intersection (split< d s0) (left s1))) (r (intersection (split> d s0) (right s1)))) (if (element? d s0) (concat3 l d r) (concat l r))))))) ;;; Exported. (define (set->list s) (let loop ((s s) (l '())) (if (empty? s) l (loop (left s) (loop (right s) (cons (data s) l)))))) ;;; Set functions defined in terms of the above ones. ;;; Exported. (define (empty-set) the-empty-set) ;;; Exported. (define (adjoin e s) (if (element? e s) s (insert e s))) ;;; Exported. (define (list->set l) (let loop ((l l) (s (empty-set))) (if (null? l) s (loop (cdr l) (adjoin (car l) s))))) ;;; Exported. (define (sum-sets sets) (let loop ((sets sets) (sum (empty-set))) (if (null? sets) sum (loop (cdr sets) (union (car sets) sum))))) ;;; Exported. (define (remove e s) (if (element? e s) (delete e s) s))