Skip to content

Commit 831b706

Browse files
splaydict
1 parent ce5775d commit 831b706

File tree

2 files changed

+245
-12
lines changed

2 files changed

+245
-12
lines changed

splaydict.erl

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
-module(splaydict).
2+
3+
-export([new/0,is_key/2,to_list/1,from_list/1,size/1]).
4+
-export([fetch/2,find/2,fetch_keys/1,erase/2]).
5+
-export([store/3,append/3,append_list/3]).
6+
-export([update_val/3,update/3,update/4,update_counter/3]).
7+
-export([fold/3,map/2,filter/2,merge/3]).
8+
9+
%% Deprecated interface.
10+
-export([dict_to_list/1,list_to_dict/1]).
11+
-deprecated([{dict_to_list,1},{list_to_dict,1}]).
12+
13+
-compile(export_all).
14+
15+
-record(splay, {
16+
lte=empty,
17+
key=undefined,
18+
value=undefined,
19+
gt=empty
20+
}).
21+
22+
%% new() -> Dict
23+
new() -> empty.
24+
25+
%% is_key(Key, Dict) -> bool()
26+
is_key(_, empty) -> false;
27+
is_key(K, #splay{lte=A, key=K1}) when K < K1 ->
28+
is_key(K, A);
29+
is_key(K, #splay{key=K1, gt=B}) when K > K1 ->
30+
is_key(K, B);
31+
is_key(_, _) -> true.
32+
33+
%% to_list(Dict) -> [{Key,Value}].
34+
to_list(T) -> to_list(T, []).
35+
36+
to_list(empty, L) -> L;
37+
to_list(#splay{lte=A, key=K, value=V, gt=B}, L) ->
38+
to_list(A, [{K, V} | to_list(B, L)]).
39+
40+
%% from_list([{Key,Value}]) -> Dict.
41+
from_list(L) ->
42+
lists:foldl(fun({K,V}, D) -> store(K, V, D) end, new(), L).
43+
44+
%% size(Dict) -> int()
45+
size(empty) -> 0;
46+
size(#splay{lte=A, gt=B}) -> splaydict:size(A) + 1 + splaydict:size(B).
47+
48+
%% fetch(Key, Dict) -> Value.
49+
50+
fetch(K, #splay{lte=A, key=K1}) when K < K1 ->
51+
fetch(K, A);
52+
fetch(K, #splay{key=K1, gt=B}) when K > K1 ->
53+
fetch(K, B);
54+
fetch(_, #splay{value=V}) -> V.
55+
56+
%% find(Key, Dict) -> {ok, Value} | error.
57+
find(_, empty) -> error;
58+
find(K, #splay{lte=A, key=K1}) when K < K1 ->
59+
find(K, A);
60+
find(K, #splay{key=K1, gt=B}) when K > K1 ->
61+
find(K, B);
62+
find(_, #splay{value=V}) -> V.
63+
64+
%% fetch_keys(Dict) -> [Key].
65+
fetch_keys(T) -> fetch_keys(T, []).
66+
67+
fetch_keys(empty, L) -> L;
68+
fetch_keys(#splay{lte=A, key=K, gt=B}, L) ->
69+
fetch_keys(A, [K | fetch_keys(B, L)]).
70+
71+
%% store(Key, Value, Dict) -> Dict.
72+
store(K, V, Dict) ->
73+
Dict1 = case has_key(K, Dict) of
74+
true -> splaydict:erase(K, Dict);
75+
false -> Dict
76+
end,
77+
{Lte, Gt} = partition(K, Dict1),
78+
#splay{lte=Lte, key=K, value=V, gt=Gt}.
79+
80+
%% append(Key, Value, Dict) -> Dict.
81+
append(K, V, empty) -> #splay{key=K, value=V};
82+
append(K, V, #splay{lte=A, key=K1}=T) when K < K1 ->
83+
T#splay{lte=append(K, V, A)};
84+
append(K, V, #splay{key=K1, gt=B}=T) when K > K1 ->
85+
T#splay{gt=append(K, V, B)};
86+
append(K, Vs, #splay{key=K, value=V1}=T) when is_list(Vs) ->
87+
T#splay{value=V1 ++ Vs};
88+
append(K, V, #splay{key=K, value=V1}=T) ->
89+
T#splay{value=V1 ++ [V]}.
90+
91+
%% append_list(K, [V], Dict) -> Dict.
92+
append_list(K, Vs, Dict) ->
93+
append(K, Vs, Dict).
94+
95+
%% has_key(K, Dict) -> bool().
96+
has_key(_, empty) -> false;
97+
has_key(K, #splay{lte=A, key=K1}) when K < K1 ->
98+
has_key(K, A);
99+
has_key(K, #splay{key=K1, gt=B}) when K > K1 ->
100+
has_key(K, B);
101+
has_key(_, _) -> true.
102+
103+
%% erase(Key, Dict) -> Dict.
104+
erase(_, empty) -> empty;
105+
erase(K, #splay{lte=A, key=K1}) when K < K1 ->
106+
erase(K, A);
107+
erase(K, #splay{key=K1, gt=B}) when K > K1 ->
108+
erase(K, B);
109+
erase(K, #splay{lte=A, key=K, gt=B}) ->
110+
merge_dict(A, B).
111+
112+
%% update_val(Key, Value, Dict) -> Dict.
113+
update_val(K, V, #splay{lte=A, key=K1}=T) when K < K1 ->
114+
T#splay{lte=update_val(K, V, A)};
115+
update_val(K, V, #splay{key=K1, gt=B}=T) when K > K1 ->
116+
T#splay{gt=update_val(K, V, B)};
117+
update_val(K, V, #splay{key=K}=T) ->
118+
T#splay{value=V}.
119+
120+
%% update(Key, Fun, Dict) -> Dict.
121+
update(K, F, #splay{lte=A, key=K1}=T) when K < K1 ->
122+
T#splay{lte=update(K, F, A)};
123+
update(K, F, #splay{key=K1, gt=B}=T) when K > K1 ->
124+
T#splay{gt=update(K, F, B)};
125+
update(K, F, #splay{key=K, value=V}=T) ->
126+
T#splay{value=F(V)}.
127+
128+
%% update(Key, Fun, Init, Dict) -> Dict.
129+
update(K, _, I, empty) -> #splay{key=K, value=I};
130+
update(K, F, I, #splay{lte=A, key=K1}=T) when K < K1 ->
131+
T#splay{lte=update(K, F, I, A)};
132+
update(K, F, I, #splay{key=K1, gt=B}=T) when K > K1 ->
133+
T#splay{gt=update(K, F, I, B)};
134+
update(K, F, _, #splay{key=K, value=V}=T) ->
135+
T#splay{value=F(V)}.
136+
137+
%% update_counter(Key, Inc, Dict) -> Dict.
138+
update_counter(K, I, empty) -> #splay{key=K, value=I};
139+
update_counter(K, I, #splay{lte=A, key=K1}=T) when K < K1 ->
140+
T#splay{lte=update_counter(K, I, A)};
141+
update_counter(K, I, #splay{key=K1, gt=B}=T) when K > K1 ->
142+
T#splay{gt=update_counter(K, I, B)};
143+
update_counter(K, I, #splay{key=K, value=V}=T) ->
144+
T#splay{value=V+I}.
145+
146+
%% del_min(Dict) -> {Dict, Element}.
147+
%del_min(#splay{lte=empty, gt=B}) -> {B, undefined};
148+
%del_min(#splay{lte=#splay{lte=empty, gt=B}, key=Y, gt=C}) ->
149+
% {#splay{lte=B, key=Y, gt=C}, Y};
150+
%del_min(#splay{lte=#splay{lte=A, key=X, gt=B}, key=Y, gt=C}) ->
151+
% {Lte, Min} = del_min(A),
152+
% {#splay{lte=Lte, key=X, gt=#splay{lte=B, key=Y, gt=C}}, Min}.
153+
154+
155+
%% fold(Fun, Acc, Dict) -> Acc.
156+
fold(_, Acc, empty) -> Acc;
157+
fold(F, Acc, #splay{lte=A, key=K, value=V, gt=B}) ->
158+
fold(F, F(K, V, fold(F, Acc, B)), A).
159+
160+
%% map(Fun, Dict) -> Dict
161+
map(_, empty) -> empty;
162+
map(F, #splay{lte=A, key=K, value=V, gt=B}=T) ->
163+
T#splay{lte=map(F, A), value=F(K, V), gt=map(F, B)}.
164+
165+
%% filter(Pred, Dict) -> Dict.
166+
%% Return elements in Dict for which Pred(Element) =:= true
167+
filter(P, T) ->
168+
filter(P, T, empty).
169+
170+
filter(_, empty, New) -> New;
171+
filter(P, #splay{lte=A, key=K, value=V, gt=B}, New0) ->
172+
New1 = filter(P, A, New0),
173+
New2 = case P(K, V) of
174+
true -> store(K, V, New1);
175+
false -> New1
176+
end,
177+
filter(P, B, New2).
178+
179+
%% merge(Fun, Dict1, Dict2) -> Dict3.
180+
merge(F, D1, D2) ->
181+
fold(fun(K, V2, D) ->
182+
update(K, fun(V1) -> F(K, V1, V2) end, V2, D)
183+
end, D1, D2).
184+
185+
merge_dict(empty, T) -> T;
186+
merge_dict(#splay{lte=A, key=K, gt=B}, T) ->
187+
{TA, TB} = partition(K, T),
188+
#splay{lte=merge_dict(TA, A), key=K, gt=merge_dict(TB, B)}.
189+
190+
partition(_Pivot, empty) -> {empty,empty};
191+
partition(Pivot, #splay{lte=A, key=K, value=V, gt=B}=T) ->
192+
case K =< Pivot of
193+
true ->
194+
case B of
195+
empty ->
196+
{T, B};
197+
#splay{lte=B1, key=K1, value=V1, gt=B2} ->
198+
case K1 =< Pivot of
199+
true ->
200+
{Lte, Gt} = partition(Pivot, B2),
201+
{#splay{lte=#splay{lte=A, key=K, value=V, gt=B1}, key=K1, value=V1, gt=Lte}, Gt};
202+
false ->
203+
{Lte, Gt} = partition(Pivot, B1),
204+
{#splay{lte=A, key=K, value=V, gt=Lte}, #splay{lte=Gt, key=K1, value=V1, gt=B2}}
205+
end
206+
end;
207+
false ->
208+
case A of
209+
empty ->
210+
{A, T};
211+
#splay{lte=A1, key=K1, value=V1, gt=A2} ->
212+
case K1 =< Pivot of
213+
true ->
214+
{Lte, Gt} = partition(Pivot, A2),
215+
{#splay{lte=A1, key=K1, value=V1, gt=Lte}, #splay{lte=Gt, key=K, value=V, gt=B}};
216+
false ->
217+
{Lte, Gt} = partition(Pivot, A1),
218+
{Lte, #splay{lte=Gt, key=K1, value=V1, gt=#splay{lte=A2, key=K, value=V, gt=B}}}
219+
end
220+
end
221+
end.
222+
223+
%find_min(#splay{lte=empty, key=Min}) -> Min;
224+
%find_min(#splay{lte=A}) -> find_min(A).
225+
226+
%% Deprecated interface.
227+
228+
%% dict_to_list(Dict) -> [{Key,Value}].
229+
dict_to_list(D) -> to_list(D).
230+
231+
%% list_to_dict([{Key,Value}]) -> Dict.
232+
list_to_dict(L) -> from_list(L).

splaysets.erl

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
-module(splaysets).
22

3-
-export([new/0, is_set/1, size/1, to_list/1, from_list/1]).
4-
-export([is_element/2, add_element/2, del_element/2]).
5-
-export([union/2, union/1, intersection/2, intersection/1]).
6-
-export([subtract/2, is_subset/2]).
7-
-export([fold/3, filter/2]).
8-
9-
-export([all/2, any/2, foreach/2, partition/2]).
10-
3+
-export([new/0,is_set/1,size/1,to_list/1,from_list/1]).
4+
-export([is_element/2,add_element/2,del_element/2]).
5+
-export([union/2,union/1,intersection/2,intersection/1]).
6+
-export([subtract/2,is_subset/2]).
7+
-export([fold/3,filter/2]).
8+
9+
%% Extended interface.
10+
-export([all/2,any/2,foreach/2,partition/2]).
11+
12+
%% Deprecated interface.
13+
1114
-export([new_set/0,set_to_list/1,list_to_set/1,subset/2]).
1215
-deprecated([{new_set,0},{set_to_list,1},{list_to_set,1},{subset,2}]).
1316

14-
-compile(export_all).
15-
1617
-record(splay, {
17-
lte={},
18+
lte=empty,
1819
data=undefined,
19-
gt={}
20+
gt=empty
2021
}).
2122

2223
%% new() -> Set

0 commit comments

Comments
 (0)