|
| 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). |
0 commit comments