1 ! Copyright (C) 2007 Alex Chapman
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs combinators
4 combinators.short-circuit kernel make math math.order namespaces
5 parser prettyprint.custom random ;
8 TUPLE: tree root { count integer } ;
12 : new-tree ( class -- tree )
26 TUPLE: node key value left right ;
28 : new-node ( key value class -- node )
33 : <node> ( key value -- node )
41 : key-side ( k1 k2 -- n )
48 : go-left? ( -- ? ) current-side get left eq? ;
50 : inc-count ( tree -- ) [ 1 + ] change-count drop ;
52 : dec-count ( tree -- ) [ 1 - ] change-count drop ;
54 : node-link@ ( node ? -- node )
55 go-left? xor [ left>> ] [ right>> ] if ;
57 : set-node-link@ ( left parent ? -- )
58 go-left? xor [ left<< ] [ right<< ] if ;
60 : node-link ( node -- child ) f node-link@ ;
62 : set-node-link ( child node -- ) f set-node-link@ ;
64 : node+link ( node -- child ) t node-link@ ;
66 : set-node+link ( child node -- ) t set-node-link@ ;
68 : with-side ( side quot -- )
69 [ current-side ] dip with-variable ; inline
71 : with-other-side ( quot -- )
72 current-side get neg swap with-side ; inline
74 : go-left ( quot -- ) left swap with-side ; inline
76 : go-right ( quot -- ) right swap with-side ; inline
79 { [ left>> not ] [ right>> not ] } 1&& ;
81 : random-side ( -- side )
82 2 random 0 eq? left right ? ;
84 : choose-branch ( key node -- key node-left/right )
85 2dup key>> key-side [ node-link ] with-side ;
87 : node-at* ( key node -- value ? )
92 choose-branch node-at*
99 : node-set ( value key node -- node )
100 2dup key>> key-side dup 0 eq? [
101 drop nip swap >>value
104 [ node-link [ node-set ] [ swap <node> ] if* ] keep
105 [ set-node-link ] keep
110 [ [ node-set ] [ swap <node> ] if* ] change-root drop ;
112 : valid-node? ( node -- ? )
115 [ dup left>> [ key>> swap key>> before? ] when* ]
116 [ dup right>> [ key>> swap key>> after? ] when* ]
117 [ left>> valid-node? ]
118 [ right>> valid-node? ]
122 : valid-tree? ( tree -- ? ) root>> valid-node? ;
124 : (node>alist) ( node -- )
126 [ left>> (node>alist) ]
127 [ [ key>> ] [ value>> ] bi 2array , ]
128 [ right>> (node>alist) ]
133 [ root>> (node>alist) ] { } make ;
139 : copy-node-contents ( new old -- new )
141 [ value>> >>value ] bi ;
146 : (prune-extremity) ( parent node -- new-extremity )
148 [ nip ] dip (prune-extremity)
150 [ delete-node ] [ set-node-link ] bi
153 : prune-extremity ( node -- new-extremity )
154 ! remove and return the leftmost or rightmost child of this node.
155 ! assumes at least one child
156 dup node-link (prune-extremity) ;
158 : replace-with-child ( node -- node )
159 dup node-link copy-node-contents dup node-link delete-node over set-node-link ;
161 : replace-with-extremity ( node -- node )
162 dup node-link dup node+link [
163 ! predecessor/successor is not the immediate child
164 [ prune-extremity ] with-other-side copy-node-contents
166 ! node-link is the predecessor/successor
167 drop replace-with-child
170 : delete-node-with-two-children ( node -- node )
171 ! randomised to minimise tree unbalancing
172 random-side [ replace-with-extremity ] with-side ;
174 : delete-node ( node -- node )
175 ! delete this node, returning its replacement
176 dup [ right>> ] [ left>> ] bi [
178 drop delete-node-with-two-children
180 nip ! left but no right
183 nip ! right but no left, or no children
186 : delete-bst-node ( key node -- node )
187 2dup key>> key-side dup 0 eq? [
191 [ node-link delete-bst-node ]
200 [ delete-bst-node ] change-root drop ;
205 M: tree clone dup assoc-clone-like ;
207 : >tree ( assoc -- tree )
208 T{ tree f f 0 } assoc-clone-like ;
210 M: tree assoc-like drop dup tree? [ >tree ] unless ;
213 \ } [ >tree ] parse-literal ;
215 M: tree assoc-size count>> ;
216 M: tree pprint-delims drop \ TREE{ \ } ;
217 M: tree >pprint-sequence >alist ;
218 M: tree pprint-narrow? drop t ;