#!r6rs (library (tokyo tojo map avl) (export map? empty? empty insert search (rename (avl:remove remove)) size (rename (avl:map map) (avl:filter filter) (avl:partition partition) (avl:for-each for-each) (avl:fold-left fold-left) (avl:fold-right fold-right))) (import (rnrs)) (define map? (lambda (x) (or (empty? x) (node? x)))) (define-record-type (avl:empty make-empty empty?) (opaque #t)) (define error-not-avl-tree (lambda (name x) (unless (map? x) (assertion-violation name "not avl tree" x)))) (define empty (make-empty)) (define-record-type (avl:node make-node node?) (fields (immutable kv key&value) (immutable l left) (immutable r right) (immutable h %height)) (opaque #t)) (define height (lambda (tr) (if (empty? tr) 0 (%height tr)))) (define balance-factor (lambda (node) (- (height (left node)) (height (right node))))) (define height+ (lambda (l r) (+ 1 (max (height l) (height r))))) ;; (-> (a p (b q c)) ;; ((a p b) q c)) (define rotate-left (lambda (p) (let ([q (right p)]) (let ([a (left p)] [b (left q)] [c (right q)]) (let ([p (make-node (key&value p) a b (height+ a b))]) (make-node (key&value q) p c (height+ p c))))))) ;; (-> ((a p b) q c) ;; (a p (b q c))) (define rotate-right (lambda (q) (let ([p (left q)]) (let ([a (left p)] [b (right p)] [c (right q)]) (let ([q (make-node (key&value q) b c (height+ b c))]) (make-node (key&value p) a q (height+ a q))))))) ;; (-> ((a p (b q c)) r d) ;; (((a p b) q c) r d) ; left rotation ;; ((a p b) q (c r d))) ; right rotation (define rotate-left-right (lambda (r) (let* ([p (left r)] [q (right p)]) (let ([a (left p)] [b (left q)] [c (right q)] [d (right r)]) (let ([p (make-node (key&value p) a b (height+ a b))] [r (make-node (key&value r) c d (height+ c d))]) (make-node (key&value q) p r (height+ p r))))))) ;; (-> (a p ((b q c) r d)) ;; (a p (b q (c r d))) ; right rotation ;; ((a p b) q (c r d))) ; left rotation (define rotate-right-left (lambda (p) (let* ([r (right p)] [q (left r)]) (let ([a (left p)] [b (left q)] [c (right q)] [d (right r)]) (let ([p (make-node (key&value p) a b (height+ a b))] [r (make-node (key&value r) c d (height+ c d))]) (make-node (key&value q) p r (height+ p r))))))) (define balance (lambda (tr) (if (empty? tr) empty (case (balance-factor tr) [(2) (case (balance-factor (left tr)) [(0 1) (rotate-right tr)] [(-1) (rotate-left-right tr)] [else (assertion-violation 'blanace "error")])] [(-2) (case (balance-factor (right tr)) [(0 -1) (rotate-left tr)] [(1) (rotate-right-left tr)] [else (assertion-violation 'blanace "error")])] [(-1 0 1) tr] [else (assertion-violation 'balance "error" (balance-factor tr) tr)])))) (define insert (case-lambda [(