From 548eaa2f5704967efe0b51ebce26bbece4061574 Mon Sep 17 00:00:00 2001 From: Masaya Tojo Date: Thu, 26 Oct 2017 07:01:45 +0900 Subject: Implement AVL Tree --- avl.ss | 312 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 avl.ss diff --git a/avl.ss b/avl.ss new file mode 100644 index 0000000..5ae4c85 --- /dev/null +++ b/avl.ss @@ -0,0 +1,312 @@ +#!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 + [(