AVL Trees
Jan Dvořák <mordae@anilinux.org>
(require avl) | package: avl |
A self-balancing binary search tree variant.
All mutations of the AVL tree create new nodes instead of modifying the data in place. The imperative variants change the root node in place for convenience. Mutating the tree is not thread-safe.
These trees could be used for as priority queues with possibility to remove elements from the middle.
1 Creating Trees
procedure
<=? : procedure?
procedure
(make-avleq <=?) → avl?
<=? : procedure?
procedure
(make-avleqv <=?) → avl?
<=? : procedure?
Like hash tables, every AVL tree variant uses a different equality predicate. make-avl uses equal?, make-avleq uses eq? and make-avleqv uses eqv?.
Tree with number? elements would use <= as the comparator, tree with string? elements would use string<=? and so on.
> (define tree (make-avleqv <=)) > (avl-add! tree 42)
procedure
(make-custom-avl <=? =?) → avl?
<=? : procedure? =? : procedure?
> (define custom-avl (make-custom-avl (λ (x y) (<= (car x) (car y))) (λ (x y) (equal? (car x) (car y))))) > (avl-add! custom-avl (cons 1 'hello)) > (avl-add! custom-avl (cons 2 'ciao)) > (avl-add! custom-avl (cons 1 'bye)) > (avl->list custom-avl) '((1 . bye) (2 . ciao))
> (define copy (avl-copy tree)) > (avl-remove! copy 42)
2 Predicates
procedure
(avl-equal? v) → boolean?
v : any/c
procedure
v : any/c
procedure
v : any/c
> (avl-equal? tree) #f
> (avl-eqv? tree) #t
> (avl-eq? tree) #f
procedure
(avl-empty? tree) → boolean?
tree : avl?
> (avl-empty? tree) #f
> (avl-empty? copy) #t
procedure
(avl-contains? tree value) → boolean?
tree : avl? value : any/c
> (avl-contains? tree 42) #t
> (avl-contains? copy 42) #f
procedure
(avl-search tree value) → any/c?
tree : avl? value : any/c
> (define animal-dict (make-custom-avl (λ (x y) (<= (car x) (car y))) (λ (x y) (equal? (car x) (car y))))) > (avl-add! animal-dict (cons 1 'cat)) > (avl-add! animal-dict (cons 2 'dog)) > (avl-add! animal-dict (cons 3 'mouse)) > (avl->list animal-dict) '((1 . cat) (2 . dog) (3 . mouse))
> (define (search-by-key tree key) (avl-search tree (cons key '()))) > (search-by-key animal-dict 1) '(1 . cat)
> (search-by-key animal-dict 2) '(2 . dog)
> (search-by-key animal-dict 3) '(3 . mouse)
> (search-by-key animal-dict 4) #f
3 Manipulating Values
> (let ((new-tree (avl-add tree 13))) (avl-contains? new-tree 13)) #t
> (avl-contains? tree 13) #f
> (avl-add! tree 13) > (avl-contains? tree 13) #t
procedure
(avl-remove tree value) → avl?
tree : avl? value : any/c
> (let ((new-tree (avl-remove tree 13))) (avl-contains? new-tree 13)) #f
> (avl-contains? tree 13) #t
procedure
(avl-remove! tree value) → void?
tree : avl? value : any/c
> (avl-remove! tree 13) > (avl-contains? tree 13) #f
procedure
(avl-mirror tree) → avl?
tree : avl?
> (let ([new-tree (make-avl <)]) (avl-add! new-tree 55) (avl-add! new-tree 10) (avl-add! new-tree 99) (avl->list (avl-mirror new-tree))) '(99 55 10)
procedure
(avl-mirror! tree) → void?
tree : avl?
> (let ([new-tree (make-avl <)]) (avl-add! new-tree 55) (avl-add! new-tree 10) (avl-add! new-tree 99) (avl-mirror! new-tree) (avl->list new-tree)) '(99 55 10)
4 Queue Usage
procedure
(avl-pop-min tree) →
any/c avl? tree : avl?
> (avl-pop-min tree)
21
#<avl>
> (avl-min tree) 21
procedure
(avl-pop-min! tree) → any/c
tree : avl?
> (avl-pop-min! tree) 21
> (avl-min tree) 42
procedure
(avl-pop-max tree) →
any/c avl? tree : avl?
> (avl-pop-max tree)
101
#<avl>
> (avl-max tree) 101
procedure
(avl-pop-max! tree) → any/c
tree : avl?
> (avl-pop-max! tree) 101
> (avl-max tree) 42
5 Iterating Over Values
procedure
(in-avl/reverse tree) → sequence?
tree : avl?
> (for/list ((value (in-avl/reverse tree))) (/ value 10)) '(21/5)