remove math.blas.syntax and merge parsing words into math.blas.vectors/matrices
[factor/jcg.git] / unmaintained / trees / avl / avl.factor
blob866e035a2134e294ba8ffbf3687cc5f748453254
1 ! Copyright (C) 2007 Alex Chapman
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: combinators kernel generic math math.functions
4 math.parser namespaces io prettyprint.backend sequences trees
5 assocs parser accessors math.order ;
6 IN: trees.avl
8 TUPLE: avl < tree ;
10 : <avl> ( -- tree )
11     avl new-tree ;
13 TUPLE: avl-node < node balance ;
15 : <avl-node> ( key value -- node )
16     avl-node new-node
17         0 >>balance ;
19 : increase-balance ( node amount -- )
20     swap [ + ] change-balance drop ;
22 : rotate ( node -- node )
23     dup node+link dup node-link pick set-node+link
24     tuck set-node-link ;    
26 : single-rotate ( node -- node )
27     0 over (>>balance) 0 over node+link 
28     (>>balance) rotate ;
30 : pick-balances ( a node -- balance balance )
31     balance>> {
32         { [ dup zero? ] [ 2drop 0 0 ] }
33         { [ over = ] [ neg 0 ] }
34         [ 0 swap ]
35     } cond ;
37 : double-rotate ( node -- node )
38     [
39         node+link [
40             node-link current-side get neg
41             over pick-balances rot 0 swap (>>balance)
42         ] keep (>>balance)
43     ] keep swap >>balance
44     dup node+link [ rotate ] with-other-side
45     over set-node+link rotate ;
47 : select-rotate ( node -- node )
48     dup node+link balance>> current-side get =
49     [ double-rotate ] [ single-rotate ] if ;
51 : balance-insert ( node -- node taller? )
52     dup avl-node-balance {
53         { [ dup zero? ] [ drop f ] }
54         { [ dup abs 2 = ]
55           [ sgn neg [ select-rotate ] with-side f ] }
56         { [ drop t ] [ t ] } ! balance is -1 or 1, tree is taller
57     } cond ;
59 DEFER: avl-set
61 : avl-insert ( value key node -- node taller? )
62     2dup node-key before? left right ? [
63         [ node-link avl-set ] keep swap
64         >r tuck set-node-link r>
65         [ dup current-side get increase-balance balance-insert ]
66         [ f ] if
67     ] with-side ;
69 : (avl-set) ( value key node -- node taller? )
70     2dup node-key = [
71         -rot pick set-node-key over set-node-value f
72     ] [ avl-insert ] if ;
74 : avl-set ( value key node -- node taller? )
75     [ (avl-set) ] [ swap <avl-node> t ] if* ;
77 M: avl set-at ( value key node -- node )
78     [ avl-set drop ] change-root drop ;
80 : delete-select-rotate ( node -- node shorter? )
81     dup node+link avl-node-balance zero? [
82         current-side get neg over set-avl-node-balance
83         current-side get over node+link set-avl-node-balance rotate f
84     ] [
85         select-rotate t
86     ] if ;
88 : rebalance-delete ( node -- node shorter? )
89     dup avl-node-balance {
90         { [ dup zero? ] [ drop t ] }
91         { [ dup abs 2 = ] [ sgn neg [ delete-select-rotate ] with-side ] }
92         { [ drop t ] [ f ] } ! balance is -1 or 1, tree is not shorter
93     } cond ;
95 : balance-delete ( node -- node shorter? )
96     current-side get over balance>> {
97         { [ dup zero? ] [ drop neg over set-avl-node-balance f ] }
98         { [ dupd = ] [ drop 0 >>balance t ] }
99         [ dupd neg increase-balance rebalance-delete ]
100     } cond ;
102 : avl-replace-with-extremity ( to-replace node -- node shorter? )
103     dup node-link [
104         swapd avl-replace-with-extremity >r over set-node-link r>
105         [ balance-delete ] [ f ] if
106     ] [
107         tuck copy-node-contents node+link t
108     ] if* ;
110 : replace-with-a-child ( node -- node shorter? )
111     #! assumes that node is not a leaf, otherwise will recurse forever
112     dup node-link [
113         dupd [ avl-replace-with-extremity ] with-other-side
114         >r over set-node-link r> [ balance-delete ] [ f ] if
115     ] [
116         [ replace-with-a-child ] with-other-side
117     ] if* ;
119 : avl-delete-node ( node -- node shorter? )
120     #! delete this node, returning its replacement, and whether this subtree is
121     #! shorter as a result
122     dup leaf? [
123         drop f t
124     ] [
125         left [ replace-with-a-child ] with-side
126     ] if ;
128 GENERIC: avl-delete ( key node -- node shorter? deleted? )
130 M: f avl-delete ( key f -- f f f ) nip f f ;
132 : (avl-delete) ( key node -- node shorter? deleted? )
133     tuck node-link avl-delete >r >r over set-node-link r>
134     [ balance-delete r> ] [ f r> ] if ;
136 M: avl-node avl-delete ( key node -- node shorter? deleted? )
137     2dup node-key key-side dup zero? [
138         drop nip avl-delete-node t
139     ] [
140         [ (avl-delete) ] with-side
141     ] if ;
143 M: avl delete-at ( key node -- )
144     [ avl-delete 2drop ] change-root drop ;
146 M: avl new-assoc 2drop <avl> ;
148 : >avl ( assoc -- avl )
149     T{ avl f f 0 } assoc-clone-like ;
151 M: avl assoc-like
152     drop dup avl? [ >avl ] unless ;
154 : AVL{
155     \ } [ >avl ] parse-literal ; parsing
157 M: avl pprint-delims drop \ AVL{ \ } ;