1 ! Copyright (C) 2007 Alex Chapman
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel generic math sequences arrays io namespaces
4 prettyprint.private kernel.private assocs random combinators
5 parser prettyprint.backend math.order accessors ;
8 TUPLE: tree root count ;
10 : new-tree ( class -- tree )
20 TUPLE: node key value left right ;
22 : new-node ( key value class -- node )
23 new swap >>value swap >>key ;
25 : <node> ( key value -- node )
30 : left ( -- symbol ) -1 ; inline
31 : right ( -- symbol ) 1 ; inline
33 : key-side ( k1 k2 -- n )
40 : go-left? ( -- ? ) current-side get left eq? ;
42 : inc-count ( tree -- ) [ 1+ ] change-count drop ;
44 : dec-count ( tree -- ) [ 1- ] change-count drop ;
46 : node-link@ ( node ? -- node )
47 go-left? xor [ left>> ] [ right>> ] if ;
48 : set-node-link@ ( left parent ? -- )
49 go-left? xor [ set-node-left ] [ set-node-right ] if ;
51 : node-link ( node -- child ) f node-link@ ;
52 : set-node-link ( child node -- ) f set-node-link@ ;
53 : node+link ( node -- child ) t node-link@ ;
54 : set-node+link ( child node -- ) t set-node-link@ ;
56 : with-side ( side quot -- ) [ swap current-side set call ] with-scope ; inline
57 : with-other-side ( quot -- )
58 current-side get neg swap with-side ; inline
59 : go-left ( quot -- ) left swap with-side ; inline
60 : go-right ( quot -- ) right swap with-side ; inline
63 [ left>> ] [ right>> ] bi or not ;
65 : random-side ( -- side ) left right 2array random ;
67 : choose-branch ( key node -- key node-left/right )
68 2dup node-key key-side [ node-link ] with-side ;
70 : node-at* ( key node -- value ? )
75 choose-branch node-at*
79 M: tree at* ( key tree -- value ? )
82 : node-set ( value key node -- node )
83 2dup key>> key-side dup 0 eq? [
87 [ node-link [ node-set ] [ swap <node> ] if* ] keep
88 [ set-node-link ] keep
92 M: tree set-at ( value key tree -- )
93 [ [ node-set ] [ swap <node> ] if* ] change-root drop ;
95 : valid-node? ( node -- ? )
97 dup dup left>> [ node-key swap node-key before? ] when* >r
98 dup dup right>> [ node-key swap node-key after? ] when* r> and swap
99 dup left>> valid-node? swap right>> valid-node? and and
102 : valid-tree? ( tree -- ? ) root>> valid-node? ;
104 : (node>alist) ( node -- )
106 [ left>> (node>alist) ]
107 [ [ node-key ] [ node-value ] bi 2array , ]
108 [ right>> (node>alist) ]
112 M: tree >alist [ root>> (node>alist) ] { } make ;
118 : copy-node-contents ( new old -- )
119 dup node-key pick set-node-key node-value swap set-node-value ;
124 : (prune-extremity) ( parent node -- new-extremity )
126 rot drop (prune-extremity)
128 tuck delete-node swap set-node-link
131 : prune-extremity ( node -- new-extremity )
132 #! remove and return the leftmost or rightmost child of this node.
133 #! assumes at least one child
134 dup node-link (prune-extremity) ;
136 : replace-with-child ( node -- node )
137 dup dup node-link copy-node-contents dup node-link delete-node over set-node-link ;
139 : replace-with-extremity ( node -- node )
140 dup node-link dup node+link [
141 ! predecessor/successor is not the immediate child
142 [ prune-extremity ] with-other-side dupd copy-node-contents
144 ! node-link is the predecessor/successor
145 drop replace-with-child
148 : delete-node-with-two-children ( node -- node )
149 #! randomised to minimise tree unbalancing
150 random-side [ replace-with-extremity ] with-side ;
152 : delete-node ( node -- node )
153 #! delete this node, returning its replacement
156 delete-node-with-two-children
158 left>> ! left but no right
162 right>> ! right but not left
168 : delete-bst-node ( key node -- node )
169 2dup node-key key-side dup 0 eq? [
172 [ tuck node-link delete-bst-node over set-node-link ] with-side
176 [ delete-bst-node ] change-root drop ;
181 M: tree clone dup assoc-clone-like ;
183 : >tree ( assoc -- tree )
184 T{ tree f f 0 } assoc-clone-like ;
186 M: tree assoc-like drop dup tree? [ >tree ] unless ;
189 \ } [ >tree ] parse-literal ; parsing
191 M: tree pprint-delims drop \ TREE{ \ } ;
192 M: tree assoc-size count>> ;
193 M: tree >pprint-sequence >alist ;
194 M: tree pprint-narrow? drop t ;