fix rb_insert and add Jan's comments.
git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@2243 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
parent
7c24afa0f2
commit
6fbe60046b
@ -17,6 +17,8 @@ xb
|
|||||||
|
|
||||||
<h2>Yap-5.1.3:</h2>
|
<h2>Yap-5.1.3:</h2>
|
||||||
<ul>
|
<ul>
|
||||||
|
<li> FIXED: do not allow duplicate values in rbtrees (obs from Jan
|
||||||
|
Wielemaker and Rui Mendes).</li>
|
||||||
<li> FIXED: handle SIGPIPE and improve USR1 and USR2 (obs from Nicos
|
<li> FIXED: handle SIGPIPE and improve USR1 and USR2 (obs from Nicos
|
||||||
Angelopoulos).</li>
|
Angelopoulos).</li>
|
||||||
<li> NEW: tmp_file/2 (request from Nicos Angelopoulos).</li>
|
<li> NEW: tmp_file/2 (request from Nicos Angelopoulos).</li>
|
||||||
|
@ -13,18 +13,18 @@
|
|||||||
|
|
||||||
:- module(rbtrees,
|
:- module(rbtrees,
|
||||||
[rb_new/1,
|
[rb_new/1,
|
||||||
rb_empty/1,
|
rb_empty/1, % ?T
|
||||||
rb_lookup/3,
|
rb_lookup/3, % +Key, -Value, +T
|
||||||
rb_update/4,
|
rb_update/4, % +T, +Key, +NewVal, -TN
|
||||||
rb_update/5,
|
rb_update/5, % +T, +Key, ?OldVal, +NewVal, -TN
|
||||||
rb_apply/4,
|
rb_apply/4, % +T, +Key, :G, -TN
|
||||||
rb_lookupall/3,
|
rb_lookupall/3, % +Key, -Value, +T
|
||||||
rb_insert/4,
|
rb_insert/4, % +T0, +Key, ?Value, -TN
|
||||||
rb_delete/3,
|
rb_delete/3, % +T, +Key, -TN
|
||||||
rb_delete/4,
|
rb_delete/4, % +T, +Key, -Val, -TN
|
||||||
rb_visit/2,
|
rb_visit/2, % +T, -Pairs
|
||||||
rb_visit/3,
|
rb_visit/3,
|
||||||
rb_keys/2,
|
rb_keys/2, % +T, +Keys
|
||||||
rb_keys/3,
|
rb_keys/3,
|
||||||
rb_map/2,
|
rb_map/2,
|
||||||
rb_map/3,
|
rb_map/3,
|
||||||
@ -44,15 +44,46 @@
|
|||||||
rb_in/3
|
rb_in/3
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
/** <module> Red black trees
|
||||||
|
|
||||||
|
Red-Black trees are balanced search binary trees. They are named because
|
||||||
|
nodes can be classified as either red or black. The code we include is
|
||||||
|
based on "Introduction to Algorithms", second edition, by Cormen,
|
||||||
|
Leiserson, Rivest and Stein. The library includes routines to insert,
|
||||||
|
lookup and delete elements in the tree.
|
||||||
|
|
||||||
|
A Red black tree is represented as a term t(Nil, Tree), where Nil is the
|
||||||
|
Nil-node, a node shared for each nil-node in the tree. Any node has the
|
||||||
|
form colour(Left, Key, Value, Right), where _colour_ is one of =red= or
|
||||||
|
=black=.
|
||||||
|
|
||||||
|
@author Vitor Santos Costa, Jan Wielemaker
|
||||||
|
*/
|
||||||
|
|
||||||
:- meta_predicate rb_map(+,:,-), rb_partial_map(+,+,:,-), rb_apply(+,+,:,-).
|
:- meta_predicate rb_map(+,:,-), rb_partial_map(+,+,:,-), rb_apply(+,+,:,-).
|
||||||
|
|
||||||
% create an empty tree.
|
% create an empty tree.
|
||||||
|
%% rb_new(-T) is det.
|
||||||
|
%
|
||||||
|
% Create a new Red-Black tree.
|
||||||
|
%
|
||||||
|
% @deprecated Use rb_empty/1.
|
||||||
|
|
||||||
rb_new(t(Nil,Nil)) :- Nil = black([],[],[],[]).
|
rb_new(t(Nil,Nil)) :- Nil = black([],[],[],[]).
|
||||||
|
|
||||||
|
%% rb_empty(?T) is semidet.
|
||||||
|
%
|
||||||
|
% Succeeds if T is an empty Red-Black tree.
|
||||||
|
|
||||||
rb_empty(t(Nil,Nil)) :- Nil = black([],[],[],[]).
|
rb_empty(t(Nil,Nil)) :- Nil = black([],[],[],[]).
|
||||||
|
|
||||||
rb_new(K,V,t(Nil,black(Nil,K,V,Nil))) :- Nil = black([],[],[],[]).
|
rb_new(K,V,t(Nil,black(Nil,K,V,Nil))) :- Nil = black([],[],[],[]).
|
||||||
|
|
||||||
|
%% rb_lookup(+Key, -Value, +T) is semidet.
|
||||||
|
%
|
||||||
|
% Backtrack through all elements with key Key in the Red-Black
|
||||||
|
% tree T, returning for each the value Value.
|
||||||
|
|
||||||
rb_lookup(Key, Val, t(_,Tree)) :-
|
rb_lookup(Key, Val, t(_,Tree)) :-
|
||||||
lookup(Key, Val, Tree).
|
lookup(Key, Val, Tree).
|
||||||
|
|
||||||
@ -71,6 +102,10 @@ lookup(<, K, V, Tree) :-
|
|||||||
lookup(=, _, V, Tree) :-
|
lookup(=, _, V, Tree) :-
|
||||||
arg(3,Tree,V).
|
arg(3,Tree,V).
|
||||||
|
|
||||||
|
%% rb_min(+T, -Key, -Value) is semidet.
|
||||||
|
%
|
||||||
|
% Key is the minimum key in T, and is associated with Val.
|
||||||
|
|
||||||
rb_min(t(_,Tree), Key, Val) :-
|
rb_min(t(_,Tree), Key, Val) :-
|
||||||
min(Tree, Key, Val).
|
min(Tree, Key, Val).
|
||||||
|
|
||||||
@ -81,6 +116,10 @@ min(red(Right,_,_,_), Key, Val) :-
|
|||||||
min(black(Right,_,_,_), Key, Val) :-
|
min(black(Right,_,_,_), Key, Val) :-
|
||||||
min(Right,Key,Val).
|
min(Right,Key,Val).
|
||||||
|
|
||||||
|
%% rb_max(+T, -Key, -Value) is semidet.
|
||||||
|
%
|
||||||
|
% Key is the maximal key in T, and is associated with Val.
|
||||||
|
|
||||||
rb_max(t(_,Tree), Key, Val) :-
|
rb_max(t(_,Tree), Key, Val) :-
|
||||||
max(Tree, Key, Val).
|
max(Tree, Key, Val).
|
||||||
|
|
||||||
@ -91,6 +130,11 @@ max(red(_,_,_,Left), Key, Val) :-
|
|||||||
max(black(_,_,_,Left), Key, Val) :-
|
max(black(_,_,_,Left), Key, Val) :-
|
||||||
max(Left,Key,Val).
|
max(Left,Key,Val).
|
||||||
|
|
||||||
|
%% rb_next(+T, +Key, -Next,-Value) is semidet.
|
||||||
|
%
|
||||||
|
% Next is the next element after Key in T, and is associated with
|
||||||
|
% Val.
|
||||||
|
|
||||||
rb_next(t(_,Tree), Key, Next, Val) :-
|
rb_next(t(_,Tree), Key, Next, Val) :-
|
||||||
next(Tree, Key, Next, Val, []).
|
next(Tree, Key, Next, Val, []).
|
||||||
|
|
||||||
@ -110,12 +154,17 @@ next(<, K, _, _, NK, V, Tree, Candidate) :-
|
|||||||
next(=, _, _, _, NK, Val, Tree, Candidate) :-
|
next(=, _, _, _, NK, Val, Tree, Candidate) :-
|
||||||
arg(4,Tree,NTree),
|
arg(4,Tree,NTree),
|
||||||
(
|
(
|
||||||
min(NTree, NK, Val) ->
|
min(NTree, NK, Val)
|
||||||
true
|
-> true
|
||||||
;
|
;
|
||||||
Candidate = NK-Val
|
Candidate = (NK-Val)
|
||||||
).
|
).
|
||||||
|
|
||||||
|
%% rb_previous(+T, +Key, -Previous, -Value) is semidet.
|
||||||
|
%
|
||||||
|
% Previous is the previous element after Key in T, and is
|
||||||
|
% associated with Val.
|
||||||
|
|
||||||
rb_previous(t(_,Tree), Key, Previous, Val) :-
|
rb_previous(t(_,Tree), Key, Previous, Val) :-
|
||||||
previous(Tree, Key, Previous, Val, []).
|
previous(Tree, Key, Previous, Val, []).
|
||||||
|
|
||||||
@ -135,12 +184,18 @@ previous(<, K, KA, VA, NK, V, Tree, _) :-
|
|||||||
previous(=, _, _, _, K, Val, Tree, Candidate) :-
|
previous(=, _, _, _, K, Val, Tree, Candidate) :-
|
||||||
arg(1,Tree,NTree),
|
arg(1,Tree,NTree),
|
||||||
(
|
(
|
||||||
max(NTree, K, Val) ->
|
max(NTree, K, Val)
|
||||||
true
|
-> true
|
||||||
;
|
;
|
||||||
Candidate = K-Val
|
Candidate = (K-Val)
|
||||||
).
|
).
|
||||||
|
|
||||||
|
%% rb_update(+T, +Key, +NewVal, -TN) is semidet.
|
||||||
|
%% rb_update(+T, +Key, ?OldVal, +NewVal, -TN) is semidet.
|
||||||
|
%
|
||||||
|
% Tree TN is tree T, but with value for Key associated with
|
||||||
|
% NewVal. Fails if it cannot find Key in T.
|
||||||
|
|
||||||
rb_update(t(Nil,OldTree), Key, OldVal, Val, t(Nil,NewTree)) :-
|
rb_update(t(Nil,OldTree), Key, OldVal, Val, t(Nil,NewTree)) :-
|
||||||
update(OldTree, Key, OldVal, Val, NewTree).
|
update(OldTree, Key, OldVal, Val, NewTree).
|
||||||
|
|
||||||
@ -150,11 +205,11 @@ rb_update(t(Nil,OldTree), Key, Val, t(Nil,NewTree)) :-
|
|||||||
update(black(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
|
update(black(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
|
||||||
Left \= [],
|
Left \= [],
|
||||||
compare(Cmp,Key0,Key),
|
compare(Cmp,Key0,Key),
|
||||||
(Cmp == = ->
|
(Cmp == (=)
|
||||||
OldVal = Val0,
|
-> OldVal = Val0,
|
||||||
NewTree = black(Left,Key0,Val,Right)
|
NewTree = black(Left,Key0,Val,Right)
|
||||||
;
|
;
|
||||||
Cmp == > ->
|
Cmp == (>) ->
|
||||||
NewTree = black(NewLeft,Key0,Val0,Right),
|
NewTree = black(NewLeft,Key0,Val0,Right),
|
||||||
update(Left, Key, OldVal, Val, NewLeft)
|
update(Left, Key, OldVal, Val, NewLeft)
|
||||||
;
|
;
|
||||||
@ -163,31 +218,38 @@ update(black(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
|
|||||||
).
|
).
|
||||||
update(red(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
|
update(red(Left,Key0,Val0,Right), Key, OldVal, Val, NewTree) :-
|
||||||
compare(Cmp,Key0,Key),
|
compare(Cmp,Key0,Key),
|
||||||
(Cmp == = ->
|
(Cmp == (=)
|
||||||
OldVal = Val0,
|
-> OldVal = Val0,
|
||||||
NewTree = red(Left,Key0,Val,Right)
|
NewTree = red(Left,Key0,Val,Right)
|
||||||
;
|
;
|
||||||
Cmp == > ->
|
Cmp == (>)
|
||||||
NewTree = red(NewLeft,Key0,Val0,Right),
|
-> NewTree = red(NewLeft,Key0,Val0,Right),
|
||||||
update(Left, Key, OldVal, Val, NewLeft)
|
update(Left, Key, OldVal, Val, NewLeft)
|
||||||
;
|
;
|
||||||
NewTree = red(Left,Key0,Val0,NewRight),
|
NewTree = red(Left,Key0,Val0,NewRight),
|
||||||
update(Right, Key, OldVal, Val, NewRight)
|
update(Right, Key, OldVal, Val, NewRight)
|
||||||
).
|
).
|
||||||
|
|
||||||
|
%% rb_apply(+T, +Key, :G, -TN) is semidet.
|
||||||
|
%
|
||||||
|
% If the value associated with key Key is Val0 in T, and if
|
||||||
|
% call(G,Val0,ValF) holds, then TN differs from T only in that Key
|
||||||
|
% is associated with value ValF in tree TN. Fails if it cannot
|
||||||
|
% find Key in T, or if call(G,Val0,ValF) is not satisfiable.
|
||||||
|
|
||||||
rb_apply(t(Nil,OldTree), Key, Goal, t(Nil,NewTree)) :-
|
rb_apply(t(Nil,OldTree), Key, Goal, t(Nil,NewTree)) :-
|
||||||
apply(OldTree, Key, Goal, NewTree).
|
apply(OldTree, Key, Goal, NewTree).
|
||||||
|
|
||||||
%apply(black([],_,_,[]), _, _, _) :- !, fail.
|
%apply(black([],_,_,[]), _, _, _) :- !, fail.
|
||||||
apply(black(Left,Key0,Val0,Right), Key, Goal, black(NewLeft,Key0,Val,NewRight)) :-
|
apply(black(Left,Key0,Val0,Right), Key, Goal,
|
||||||
|
black(NewLeft,Key0,Val,NewRight)) :-
|
||||||
Left \= [],
|
Left \= [],
|
||||||
compare(Cmp,Key0,Key),
|
compare(Cmp,Key0,Key),
|
||||||
(Cmp == (=) ->
|
(Cmp == (=)
|
||||||
NewLeft = Left,
|
-> NewLeft = Left,
|
||||||
NewRight = Right,
|
NewRight = Right,
|
||||||
call(Goal,Val0,Val)
|
call(Goal,Val0,Val)
|
||||||
;
|
; Cmp == (>) ->
|
||||||
Cmp == (>) ->
|
|
||||||
NewRight = Right,
|
NewRight = Right,
|
||||||
Val = Val0,
|
Val = Val0,
|
||||||
apply(Left, Key, Goal, NewLeft)
|
apply(Left, Key, Goal, NewLeft)
|
||||||
@ -196,15 +258,15 @@ apply(black(Left,Key0,Val0,Right), Key, Goal, black(NewLeft,Key0,Val,NewRight))
|
|||||||
Val = Val0,
|
Val = Val0,
|
||||||
apply(Right, Key, Goal, NewRight)
|
apply(Right, Key, Goal, NewRight)
|
||||||
).
|
).
|
||||||
apply(red(Left,Key0,Val0,Right), Key, Goal, red(NewLeft,Key0,Val,NewRight)) :-
|
apply(red(Left,Key0,Val0,Right), Key, Goal,
|
||||||
|
red(NewLeft,Key0,Val,NewRight)) :-
|
||||||
compare(Cmp,Key0,Key),
|
compare(Cmp,Key0,Key),
|
||||||
(Cmp == (=) ->
|
( Cmp == (=)
|
||||||
NewLeft = Left,
|
-> NewLeft = Left,
|
||||||
NewRight = Right,
|
NewRight = Right,
|
||||||
call(Goal,Val0,Val)
|
call(Goal,Val0,Val)
|
||||||
;
|
; Cmp == (>)
|
||||||
Cmp == (>) ->
|
-> NewRight = Right,
|
||||||
NewRight = Right,
|
|
||||||
Val = Val0,
|
Val = Val0,
|
||||||
apply(Left, Key, Goal, NewLeft)
|
apply(Left, Key, Goal, NewLeft)
|
||||||
;
|
;
|
||||||
@ -213,6 +275,10 @@ apply(red(Left,Key0,Val0,Right), Key, Goal, red(NewLeft,Key0,Val,NewRight)) :-
|
|||||||
apply(Right, Key, Goal, NewRight)
|
apply(Right, Key, Goal, NewRight)
|
||||||
).
|
).
|
||||||
|
|
||||||
|
%% rb_in(?Key, ?Val, +Tree) is nondet.
|
||||||
|
%
|
||||||
|
% True if Key-Val appear in Tree. Uses indexing if Key is bound.
|
||||||
|
|
||||||
rb_in(Key, Val, t(_,T)) :-
|
rb_in(Key, Val, t(_,T)) :-
|
||||||
var(Key), !,
|
var(Key), !,
|
||||||
enum(Key, Val, T).
|
enum(Key, Val, T).
|
||||||
@ -233,6 +299,11 @@ enum_cases(Key, Val, _, _, _, R) :-
|
|||||||
enum(Key, Val, R).
|
enum(Key, Val, R).
|
||||||
|
|
||||||
|
|
||||||
|
%% rb_lookupall(+Key, -Value, +T)
|
||||||
|
%
|
||||||
|
% Lookup all elements with key Key in the red-black tree T,
|
||||||
|
% returning the value Value.
|
||||||
|
|
||||||
rb_lookupall(Key, Val, t(_,Tree)) :-
|
rb_lookupall(Key, Val, t(_,Tree)) :-
|
||||||
lookupall(Key, Val, Tree).
|
lookupall(Key, Val, Tree).
|
||||||
|
|
||||||
@ -255,11 +326,17 @@ lookupall(<, K, V, Tree) :-
|
|||||||
arg(1,Tree,NTree),
|
arg(1,Tree,NTree),
|
||||||
lookupall(K, V, NTree).
|
lookupall(K, V, NTree).
|
||||||
|
|
||||||
%
|
/*******************************
|
||||||
% Tree insertion
|
* TREE INSERTION *
|
||||||
%
|
*******************************/
|
||||||
|
|
||||||
% We don't use parent nodes, so we may have to fix the root.
|
% We don't use parent nodes, so we may have to fix the root.
|
||||||
|
|
||||||
|
%% rb_insert(+T0, +Key, ?Value, -TN)
|
||||||
%
|
%
|
||||||
|
% Add an element with key Key and Value to the tree T0 creating a
|
||||||
|
% new red-black tree TN. Duplicated elements are not allowed.
|
||||||
|
|
||||||
rb_insert(t(Nil,Tree0),Key,Val,t(Nil,Tree)) :-
|
rb_insert(t(Nil,Tree0),Key,Val,t(Nil,Tree)) :-
|
||||||
insert(Tree0,Key,Val,Nil,Tree).
|
insert(Tree0,Key,Val,Nil,Tree).
|
||||||
|
|
||||||
@ -302,17 +379,23 @@ insert2(black([],[],[],[]), K, V, Nil, T, Status) :- !,
|
|||||||
T = red(Nil,K,V,Nil),
|
T = red(Nil,K,V,Nil),
|
||||||
Status = not_done.
|
Status = not_done.
|
||||||
insert2(red(L,K0,V0,R), K, V, Nil, red(NL,K0,V0,NR), Flag) :-
|
insert2(red(L,K0,V0,R), K, V, Nil, red(NL,K0,V0,NR), Flag) :-
|
||||||
( K @< K0 ->
|
( K @< K0
|
||||||
NR = R,
|
-> NR = R,
|
||||||
insert2(L, K, V, Nil, NL, Flag)
|
insert2(L, K, V, Nil, NL, Flag)
|
||||||
|
; K == K0 ->
|
||||||
|
NT = red(L,K0,V,R),
|
||||||
|
Flag = done
|
||||||
;
|
;
|
||||||
NL = L,
|
NL = L,
|
||||||
insert2(R, K, V, Nil, NR, Flag)
|
insert2(R, K, V, Nil, NR, Flag)
|
||||||
).
|
).
|
||||||
insert2(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
|
insert2(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
|
||||||
( K @< K0 ->
|
( K @< K0
|
||||||
insert2(L, K, V, Nil, IL, Flag0),
|
-> insert2(L, K, V, Nil, IL, Flag0),
|
||||||
fix_left(Flag0, black(IL,K0,V0,R), NT, Flag)
|
fix_left(Flag0, black(IL,K0,V0,R), NT, Flag)
|
||||||
|
; K == K0 ->
|
||||||
|
NT = black(L,K0,V,R),
|
||||||
|
Flag = done
|
||||||
;
|
;
|
||||||
insert2(R, K, V, Nil, IR, Flag0),
|
insert2(R, K, V, Nil, IR, Flag0),
|
||||||
fix_right(Flag0, black(L,K0,V0,IR), NT, Flag)
|
fix_right(Flag0, black(L,K0,V0,IR), NT, Flag)
|
||||||
@ -407,6 +490,12 @@ pretty_print(black(L,K,_,R),D) :-
|
|||||||
rb_delete(t(Nil,T), K, t(Nil,NT)) :-
|
rb_delete(t(Nil,T), K, t(Nil,NT)) :-
|
||||||
delete(T, K, _, NT, _).
|
delete(T, K, _, NT, _).
|
||||||
|
|
||||||
|
%% rb_delete(+T, +Key, -TN).
|
||||||
|
%% rb_delete(+T, +Key, -Val, -TN).
|
||||||
|
%
|
||||||
|
% Delete element with key Key from the tree T, returning the value
|
||||||
|
% Val associated with the key and a new tree TN.
|
||||||
|
|
||||||
rb_delete(t(Nil,T), K, V, t(Nil,NT)) :-
|
rb_delete(t(Nil,T), K, V, t(Nil,NT)) :-
|
||||||
delete(T, K, V, NT, _).
|
delete(T, K, V, NT, _).
|
||||||
|
|
||||||
@ -436,6 +525,11 @@ delete(black(L,_,V,R), _, V, OUT, Flag) :-
|
|||||||
% K == K0,
|
% K == K0,
|
||||||
delete_black_node(L,R,OUT,Flag).
|
delete_black_node(L,R,OUT,Flag).
|
||||||
|
|
||||||
|
%% rb_del_min(+T, -Key, -Val, -TN)
|
||||||
|
%
|
||||||
|
% Delete the least element from the tree T, returning the key Key,
|
||||||
|
% the value Val associated with the key and a new tree TN.
|
||||||
|
|
||||||
rb_del_min(t(Nil,T), K, Val, t(Nil,NT)) :-
|
rb_del_min(t(Nil,T), K, Val, t(Nil,NT)) :-
|
||||||
del_min(T, K, Val, Nil, NT, _).
|
del_min(T, K, Val, Nil, NT, _).
|
||||||
|
|
||||||
@ -451,6 +545,11 @@ del_min(black(L,K0,V0,R), K, V, Nil, NT, Flag) :-
|
|||||||
fixup_left(Flag0,black(NL,K0,V0,R),NT, Flag).
|
fixup_left(Flag0,black(NL,K0,V0,R),NT, Flag).
|
||||||
|
|
||||||
|
|
||||||
|
%% rb_del_max(+T, -Key, -Val, -TN)
|
||||||
|
%
|
||||||
|
% Delete the largest element from the tree T, returning the key
|
||||||
|
% Key, the value Val associated with the key and a new tree TN.
|
||||||
|
|
||||||
rb_del_max(t(Nil,T), K, Val, t(Nil,NT)) :-
|
rb_del_max(t(Nil,T), K, Val, t(Nil,NT)) :-
|
||||||
del_max(T, K, Val, Nil, NT, _).
|
del_max(T, K, Val, Nil, NT, _).
|
||||||
|
|
||||||
@ -584,6 +683,12 @@ fixup3(black(black(red(Fi,KE,VE,Ep),KD,VD,C),KB,VB,black(Be,KA,VA,Al)),
|
|||||||
%
|
%
|
||||||
% whole list
|
% whole list
|
||||||
%
|
%
|
||||||
|
|
||||||
|
%% rb_visit(+T, -Pairs)
|
||||||
|
%
|
||||||
|
% Pairs is an infix visit of tree T, where each element of Pairs
|
||||||
|
% is of the form K-Val.
|
||||||
|
|
||||||
rb_visit(t(_,T),Lf) :-
|
rb_visit(t(_,T),Lf) :-
|
||||||
visit(T,[],Lf).
|
visit(T,[],Lf).
|
||||||
|
|
||||||
@ -598,10 +703,21 @@ visit(black(L,K,V,R),L0,Lf) :-
|
|||||||
visit(L,[K-V|L1],Lf),
|
visit(L,[K-V|L1],Lf),
|
||||||
visit(R,L0,L1).
|
visit(R,L0,L1).
|
||||||
|
|
||||||
|
%% rb_map(+T, :Goal) is semidet.
|
||||||
|
%
|
||||||
|
% True if call(Goal, Value) is true for all nodes in T.
|
||||||
|
|
||||||
rb_map(t(Nil,Tree),Goal,t(Nil,NewTree)) :-
|
rb_map(t(Nil,Tree),Goal,t(Nil,NewTree)) :-
|
||||||
map(Tree,Goal,NewTree).
|
map(Tree,Goal,NewTree).
|
||||||
|
|
||||||
|
|
||||||
|
%% rb_map(+T, :G, -TN) is semidet.
|
||||||
|
%
|
||||||
|
% For all nodes Key in the tree T, if the value associated with
|
||||||
|
% key Key is Val0 in tree T, and if call(G,Val0,ValF) holds, then
|
||||||
|
% the value associated with Key in TN is ValF. Fails if
|
||||||
|
% call(G,Val0,ValF) is not satisfiable for all Var0.
|
||||||
|
|
||||||
map(black([],[],[],[]),_,black([],[],[],[])) :- !.
|
map(black([],[],[],[]),_,black([],[],[],[])) :- !.
|
||||||
map(red(L,K,V,R),Goal,red(NL,K,NV,NR)) :-
|
map(red(L,K,V,R),Goal,red(NL,K,NV,NR)) :-
|
||||||
call(Goal,V,NV), !,
|
call(Goal,V,NV), !,
|
||||||
@ -626,6 +742,12 @@ map(black(L,_,V,R),Goal) :-
|
|||||||
map(L,Goal),
|
map(L,Goal),
|
||||||
map(R,Goal).
|
map(R,Goal).
|
||||||
|
|
||||||
|
%% rb_clone(+T, -NT, -Pairs)
|
||||||
|
%
|
||||||
|
% "Clone" the red-back tree into a new tree with the same keys as
|
||||||
|
% the original but with all values set to unbound values. Nodes is
|
||||||
|
% a list containing all new nodes as pairs K-V.
|
||||||
|
|
||||||
rb_clone(t(Nil,T),t(Nil,NT),Ns) :-
|
rb_clone(t(Nil,T),t(Nil,NT),Ns) :-
|
||||||
clone(T,NT,Ns,[]).
|
clone(T,NT,Ns,[]).
|
||||||
|
|
||||||
@ -648,6 +770,14 @@ clone(black(L,K,V,R),ONsF,ONs0,black(NL,K,NV,NR),NsF,Ns0) :-
|
|||||||
clone(L,ONsF,[K-V|ONs1],NL,NsF,[K-NV|Ns1]),
|
clone(L,ONsF,[K-V|ONs1],NL,NsF,[K-NV|Ns1]),
|
||||||
clone(R,ONs1,ONs0,NR,Ns1,Ns0).
|
clone(R,ONs1,ONs0,NR,Ns1,Ns0).
|
||||||
|
|
||||||
|
%% rb_partial_map(+T, +Keys, :G, -TN)
|
||||||
|
%
|
||||||
|
% For all nodes Key in Keys, if the value associated with key Key
|
||||||
|
% is Val0 in tree T, and if call(G,Val0,ValF) holds, then the
|
||||||
|
% value associated with Key in TN is ValF. Fails if or if
|
||||||
|
% call(G,Val0,ValF) is not satisfiable for all Var0. Assumes keys
|
||||||
|
% are not repeated.
|
||||||
|
|
||||||
rb_partial_map(t(Nil,T0), Map, Goal, t(Nil,TF)) :-
|
rb_partial_map(t(Nil,T0), Map, Goal, t(Nil,TF)) :-
|
||||||
partial_map(T0, Map, [], Nil, Goal, TF).
|
partial_map(T0, Map, [], Nil, Goal, TF).
|
||||||
|
|
||||||
@ -697,6 +827,11 @@ partial_map(black(L,K,V,R),Map,MapF,Nil,Goal,black(NL,K,NV,NR)) :-
|
|||||||
%
|
%
|
||||||
% whole keys
|
% whole keys
|
||||||
%
|
%
|
||||||
|
%% rb_keys(+T, -Keys)
|
||||||
|
%
|
||||||
|
% Keys is unified with an ordered list of all keys in the
|
||||||
|
% Red-Black tree T.
|
||||||
|
|
||||||
rb_keys(t(_,T),Lf) :-
|
rb_keys(t(_,T),Lf) :-
|
||||||
keys(T,[],Lf).
|
keys(T,[],Lf).
|
||||||
|
|
||||||
@ -712,21 +847,10 @@ keys(black(L,K,_,R),L0,Lf) :-
|
|||||||
keys(R,L0,L1).
|
keys(R,L0,L1).
|
||||||
|
|
||||||
|
|
||||||
ord_list_to_rbtree(List,Tree) :-
|
%% list_to_rbtree(+L, -T) is det.
|
||||||
list_to_rbtree(List,Tree).
|
%
|
||||||
|
% T is the red-black tree corresponding to the mapping in list L.
|
||||||
|
|
||||||
list_to_rbtree(List,Tree) :-
|
|
||||||
rb_new(T0),
|
|
||||||
list_to_rbtree(List,T0,Tree).
|
|
||||||
|
|
||||||
list_to_rbtree([],Tree,Tree).
|
|
||||||
list_to_rbtree([K-V|List],T0,Tree) :-
|
|
||||||
rb_insert(T0, K, V, T1),
|
|
||||||
list_to_rbtree(List,T1,Tree).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
list_to_rbtree(List, t(Nil,Tree)) :-
|
list_to_rbtree(List, t(Nil,Tree)) :-
|
||||||
Nil = black([], [], [], []),
|
Nil = black([], [], [], []),
|
||||||
sort(List,Sorted),
|
sort(List,Sorted),
|
||||||
@ -734,12 +858,16 @@ list_to_rbtree(List,t(Nil,Tree)) :-
|
|||||||
functor(Ar,_,L),
|
functor(Ar,_,L),
|
||||||
construct_rbtree(1, L, Ar, black, Nil, Tree).
|
construct_rbtree(1, L, Ar, black, Nil, Tree).
|
||||||
|
|
||||||
|
%% ord_list_to_rbtree(+L, -T) is det.
|
||||||
|
%
|
||||||
|
% T is the red-black tree corresponding to the mapping in ordered
|
||||||
|
% list L.
|
||||||
|
|
||||||
ord_list_to_rbtree(List, t(Nil,Tree)) :-
|
ord_list_to_rbtree(List, t(Nil,Tree)) :-
|
||||||
Nil = black([], [], [], []),
|
Nil = black([], [], [], []),
|
||||||
Ar =.. [seq|List],
|
Ar =.. [seq|List],
|
||||||
functor(Ar,_,L),
|
functor(Ar,_,L),
|
||||||
construct_rbtree(1, L, Ar, black, Nil, Tree).
|
construct_rbtree(1, L, Ar, black, Nil, Tree).
|
||||||
*/
|
|
||||||
|
|
||||||
construct_rbtree(L, M, _, _, Nil, Nil) :- M < L, !.
|
construct_rbtree(L, M, _, _, Nil, Nil) :- M < L, !.
|
||||||
construct_rbtree(L, L, Ar, Color, Nil, Node) :- !,
|
construct_rbtree(L, L, Ar, Color, Nil, Node) :- !,
|
||||||
@ -757,6 +885,11 @@ construct_rbtree(I0, Max, Ar, Color, Nil, Node) :-
|
|||||||
build_node(black, Left, K, Val, Right, black(Left, K, Val, Right), red).
|
build_node(black, Left, K, Val, Right, black(Left, K, Val, Right), red).
|
||||||
build_node(red, Left, K, Val, Right, red(Left, K, Val, Right), black).
|
build_node(red, Left, K, Val, Right, red(Left, K, Val, Right), black).
|
||||||
|
|
||||||
|
|
||||||
|
%% rb_size(+T, -Size) is det.
|
||||||
|
%
|
||||||
|
% Size is the number of elements in T.
|
||||||
|
|
||||||
rb_size(t(_,T),Size) :-
|
rb_size(t(_,T),Size) :-
|
||||||
size(T,0,Size).
|
size(T,0,Size).
|
||||||
|
|
||||||
@ -770,6 +903,14 @@ size(black(L,_,_,R),Sz0,Szf) :-
|
|||||||
size(L,Sz1,Sz2),
|
size(L,Sz1,Sz2),
|
||||||
size(R,Sz2,Szf).
|
size(R,Sz2,Szf).
|
||||||
|
|
||||||
|
%% is_rbtree(?Term) is semidet.
|
||||||
|
%
|
||||||
|
% True if Term is a valide Red-Black tree.
|
||||||
|
%
|
||||||
|
% @tbd Catch variables.
|
||||||
|
|
||||||
|
is_rbtree(X) :-
|
||||||
|
var(X), !, fail.
|
||||||
is_rbtree(t(Nil,Nil)) :- !.
|
is_rbtree(t(Nil,Nil)) :- !.
|
||||||
is_rbtree(t(_,T)) :-
|
is_rbtree(t(_,T)) :-
|
||||||
catch(rbtree1(T), msg(_,_), fail).
|
catch(rbtree1(T), msg(_,_), fail).
|
||||||
|
Reference in New Issue
Block a user