34
35:- module(nb_rbtrees,
36 [ nb_rb_insert/3, 37 nb_rb_get_node/3, 38 nb_rb_node_value/2, 39 nb_rb_set_node_value/2 40 ]).
54
63nb_rb_insert(Tree, Key0, Val0) :-
64 duplicate_term(Key0, Key),
65 duplicate_term(Val0, Val),
66 Tree = t(Nil, T),
67 insert(T, Key, Val, Nil, NT, Flag),
68 ( Flag == shared
69 -> true
70 ; nb_linkarg(2, Tree, NT)
71 ).
72
73insert(Tree0,Key,Val,Nil,Tree, Flag) :-
74 insert2(Tree0,Key,Val,Nil,TreeI,Flag),
75 ( Flag == shared
76 -> Tree = Tree0
77 ; fix_root(TreeI,Tree)
78 ).
79
83fix_root(black(L,K,V,R),black(L,K,V,R)).
84fix_root(red(L,K,V,R),black(L,K,V,R)).
85
86
104
105
106
110insert2(black('',_,_,''), K, V, Nil, T, Status) :-
111 !,
112 T = red(Nil,K,V,Nil),
113 Status = not_done.
114insert2(In, K, V, Nil, NT, Flag) :-
115 In = red(L,K0,V0,R),
116 !,
117 ( K @< K0
118 -> insert2(L, K, V, Nil, NL, Flag),
119 ( Flag == shared
120 -> NT = In
121 ; NT = red(NL,K0,V0,R)
122 )
123 ; insert2(R, K, V, Nil, NR, Flag),
124 ( Flag == shared
125 -> NT = In
126 ; NT = red(L,K0,V0,NR)
127 )
128 ).
129insert2(In, K, V, Nil, NT, Flag) :-
130 In = black(L,K0,V0,R),
131 ( K @< K0
132 -> insert2(L, K, V, Nil, IL, Flag0),
133 ( Flag0 == shared
134 -> NT = In
135 ; fix_left(Flag0, black(IL,K0,V0,R), NT0, Flag1),
136 ( Flag1 == share
137 -> nb_linkarg(1, In, IL),
138 Flag = shared,
139 NT = In
140 ; NT = NT0,
141 Flag = Flag1
142 )
143 )
144 ; insert2(R, K, V, Nil, IR, Flag0),
145 ( Flag0 == shared
146 -> NT = In
147 ; fix_right(Flag0, black(L,K0,V0,IR), NT0, Flag1),
148 ( Flag1 == share
149 -> nb_linkarg(4, In, IR),
150 Flag = shared,
151 NT = In
152 ; NT = NT0,
153 Flag = Flag1
154 )
155 )
156 ).
157
161fix_left(shared,T,T,shared) :- !.
162fix_left(done,T,T,done) :- !.
163fix_left(not_done,Tmp,Final,Done) :-
164 fix_left(Tmp,Final,Done).
165
169fix_left(black(red(Al,AK,AV,red(Be,BK,BV,Ga)),KC,VC,red(De,KD,VD,Ep)),
170 red(black(Al,AK,AV,red(Be,BK,BV,Ga)),KC,VC,black(De,KD,VD,Ep)),
171 not_done) :- !.
172fix_left(black(red(red(Al,KA,VA,Be),KB,VB,Ga),KC,VC,red(De,KD,VD,Ep)),
173 red(black(red(Al,KA,VA,Be),KB,VB,Ga),KC,VC,black(De,KD,VD,Ep)),
174 not_done) :- !.
178fix_left(black(red(Al,KA,VA,red(Be,KB,VB,Ga)),KC,VC,De),
179 black(red(Al,KA,VA,Be),KB,VB,red(Ga,KC,VC,De)),
180 done) :- !.
184fix_left(black(red(red(Al,KA,VA,Be),KB,VB,Ga),KC,VC,De),
185 black(red(Al,KA,VA,Be),KB,VB,red(Ga,KC,VC,De)),
186 done) :- !.
190fix_left(T,T,share). 191
195fix_right(shared,T,T,shared) :- !.
196fix_right(done,T,T,done) :- !.
197fix_right(not_done,Tmp,Final,Done) :-
198 fix_right(Tmp,Final,Done).
199
203fix_right(black(red(Ep,KD,VD,De),KC,VC,red(red(Ga,KB,VB,Be),KA,VA,Al)),
204 red(black(Ep,KD,VD,De),KC,VC,black(red(Ga,KB,VB,Be),KA,VA,Al)),
205 not_done) :- !.
206fix_right(black(red(Ep,KD,VD,De),KC,VC,red(Ga,Ka,Va,red(Be,KB,VB,Al))),
207 red(black(Ep,KD,VD,De),KC,VC,black(Ga,Ka,Va,red(Be,KB,VB,Al))),
208 not_done) :- !.
212fix_right(black(De,KC,VC,red(red(Ga,KB,VB,Be),KA,VA,Al)),
213 black(red(De,KC,VC,Ga),KB,VB,red(Be,KA,VA,Al)),
214 done) :- !.
218fix_right(black(De,KC,VC,red(Ga,KB,VB,red(Be,KA,VA,Al))),
219 black(red(De,KC,VC,Ga),KB,VB,red(Be,KA,VA,Al)),
220 done) :- !.
224fix_right(T,T,share).
225
226
227
238nb_rb_get_node(t(_Nil, Tree), Key, Node) :-
239 find_node(Key, Tree, Node).
240
241find_node(Key, Tree, Node) :-
242 Tree \== '',
243 arg(2, Tree, K),
244 compare(Diff, Key, K),
245 find_node(Diff, Key, Tree, Node).
246
247find_node(=, _, Node, Node).
248find_node(<, Key, Tree, Node) :-
249 arg(1, Tree, Left),
250 find_node(Key, Left, Node).
251find_node(>, Key, Tree, Node) :-
252 arg(4, Tree, Right),
253 find_node(Key, Right, Node).
259nb_rb_node_value(Node, Value) :-
260 arg(3, Node, Value).
266nb_rb_set_node_value(Node, Value) :-
267 nb_setarg(3, Node, Value)
Non-backtrackable operations on red black trees
This library is an extension to
rbtrees.pl
, implementing Red-black trees. This library adds non-backtrackable destructive update to RB trees which allows us to fill RB trees in a failure driven loop.This module builds on top of the
rbtrees.pl
and used code copied from library written by Vitor Santos Costa.