Skip to content

Commit d25c0f3

Browse files
committed
optimization to construct rbtree from sorted list
1 parent aaf3797 commit d25c0f3

File tree

3 files changed

+85
-81
lines changed

3 files changed

+85
-81
lines changed

stdlib/lm_set.ml

Lines changed: 85 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@
3333
* modify it under the terms of the GNU Lesser General Public
3434
* License as published by the Free Software Foundation,
3535
* version 2.1 of the License.
36-
*
36+
*
3737
* This library is distributed in the hope that it will be useful,
3838
* but WITHOUT ANY WARRANTY; without even the implied warranty of
3939
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4040
* Lesser General Public License for more details.
41-
*
41+
*
4242
* You should have received a copy of the GNU Lesser General Public
4343
* License along with this library; if not, write to the Free Software
4444
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
45-
*
45+
*
4646
* Additional permission is given to link this library with the
4747
* OpenSSL project's "OpenSSL" library, and with the OCaml runtime,
4848
* and you may distribute the linked executables. See the file
@@ -1022,6 +1022,47 @@ struct
10221022
let max_depth = pred (log2 1 (succ length)) in
10231023
of_sorted_array 0 max_depth elements 0 length
10241024

1025+
(*
1026+
* Following treeify function are taken from Appel's Efficient Verified Red-Black Trees
1027+
*)
1028+
let rec treeify_f n l =
1029+
if n = 1 then
1030+
match l with
1031+
x :: l -> Red (x, Leaf, Leaf, 1), l
1032+
| _ -> raise (invalid_arg "treeify")
1033+
else
1034+
let h = n lsr 1 in
1035+
let f = if n mod 2 = 0 then
1036+
treeify_g
1037+
else
1038+
treeify_f
1039+
in
1040+
match treeify_f h l with
1041+
(left, x :: l) -> let right, l' = f h l
1042+
in new_black x left right, l'
1043+
| _ -> raise (invalid_arg "treeify")
1044+
1045+
and treeify_g n l =
1046+
if n = 1 then
1047+
Leaf, l
1048+
else
1049+
let h = n lsr 1 in
1050+
let f = if n mod 2 = 0 then
1051+
treeify_g
1052+
else
1053+
treeify_f
1054+
in
1055+
match f h l with
1056+
(left, x :: l) -> let right, l' = treeify_g h l
1057+
in new_black x left right, l'
1058+
| _ -> raise (invalid_arg "treeify")
1059+
1060+
(*
1061+
* Build a tree directly from ordered list,
1062+
* take length + 1 of the list.
1063+
*)
1064+
let treeify n l = (fst (treeify_g n l))
1065+
10251066
(*
10261067
* Convert to a list.
10271068
*)
@@ -1046,6 +1087,7 @@ struct
10461087
| Leaf ->
10471088
s1
10481089

1090+
(* TODO: LDB: implement linear union *)
10491091
let union s1 s2 =
10501092
let size1 = cardinality s1 in
10511093
let size2 = cardinality s2 in
@@ -1154,6 +1196,19 @@ struct
11541196
| Leaf ->
11551197
arg
11561198

1199+
(*
1200+
* Fold in reverse direction, useful for define
1201+
* other operations.
1202+
*)
1203+
let rec fold_r f arg = function
1204+
Black (key, left, right, _)
1205+
| Red (key, left, right, _) ->
1206+
let arg = fold_r f arg right in
1207+
let arg = f arg key in
1208+
fold_r f arg left
1209+
| Leaf ->
1210+
arg
1211+
11571212
(*
11581213
* Equality of sets.
11591214
*)
@@ -1166,15 +1221,17 @@ struct
11661221
false
11671222

11681223
(*
1169-
* BUG: these functions are too slow!
1170-
* Could be much more optimized.
1224+
* Optimization by construct the tree directly.
11711225
*)
1226+
let add_item i (n, l) = (succ n, i :: l)
1227+
11721228
let filter pred s =
1173-
fold (fun s' x ->
1174-
if pred x then
1175-
add s' x
1176-
else
1177-
s') empty s
1229+
let n, l = fold_r (fun s x ->
1230+
if pred x then
1231+
add_item x s
1232+
else
1233+
s) (1, []) s
1234+
in treeify n l
11781235

11791236
let inter s1 s2 =
11801237
let size1 = cardinality s1 in
@@ -1183,20 +1240,23 @@ struct
11831240
if size1 < size2 then
11841241
s1, s2
11851242
else
1186-
s2, s1
1187-
in
1188-
fold (fun s3 x ->
1189-
if mem s2 x then
1190-
add s3 x
1191-
else
1192-
s3) empty s1
1243+
s2, s1 in
1244+
let n, l = fold_r (fun s3 x ->
1245+
if mem s2 x then
1246+
add_item x s3
1247+
else
1248+
s3) (1, []) s1
1249+
in treeify n l
11931250

11941251
let partition pred s =
1195-
fold (fun (s1, s2) x ->
1196-
if pred x then
1197-
add s1 x, s2
1198-
else
1199-
s1, add s2 x) (empty, empty) s
1252+
let (n1, l1), l2 =
1253+
fold_r (fun (s1, s2) x ->
1254+
if pred x then
1255+
add_item x s1, s2
1256+
else
1257+
s1, x :: s2) ((1, []), []) s in
1258+
let n2 = cardinality s - n1 + 2
1259+
in treeify n1 l1, treeify n2 l2
12001260

12011261
let rec diff s = function
12021262
Black (key, left, right, _)
@@ -1219,9 +1279,9 @@ struct
12191279

12201280
let compare s1 s2 =
12211281
let rec compare s1 s2 =
1222-
match s1, s2 with
1223-
x1 :: s1, x2 :: s2 ->
1224-
let cmp = Ord.compare x1 x2 in
1282+
match s1, s2 with
1283+
x1 :: s1, x2 :: s2 ->
1284+
let cmp = Ord.compare x1 x2 in
12251285
if cmp = 0 then
12261286
compare s1 s2
12271287
else
@@ -1357,28 +1417,6 @@ struct
13571417
let print = pp_print
13581418
end
13591419

1360-
module Make (Ord : OrderedType) : S with type elt = Ord.t =
1361-
struct
1362-
module XSet = LmMake (Ord)
1363-
1364-
include XSet
1365-
1366-
let mem x s =
1367-
XSet.mem s x
1368-
1369-
let add x s =
1370-
XSet.add s x
1371-
1372-
let remove x s =
1373-
XSet.remove s x
1374-
1375-
let fold f s x =
1376-
XSet.fold (fun x y -> f y x) x s
1377-
1378-
let partition f s =
1379-
fst (XSet.partition f s)
1380-
end
1381-
13821420
(*
13831421
* -*-
13841422
* Local Variables:

stdlib/lm_set.mli

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,3 @@ open Lm_set_sig
3838

3939
module LmMake (Ord : OrderedType) : (LmSet with type elt = Ord.t)
4040
module LmMakeDebug (Ord : OrderedTypeDebug) : (LmSetDebug with type elt = Ord.t)
41-
module Make (Ord : OrderedType) : (S with type elt = Ord.t)

stdlib/lm_set_sig.ml

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -149,39 +149,6 @@ sig
149149
val print : Lm_printf.out_channel -> t -> unit
150150
end
151151

152-
(*
153-
* Backwards-compatible version.
154-
*)
155-
module type S =
156-
sig
157-
type elt
158-
type t
159-
160-
val empty : t
161-
val is_empty : t -> bool
162-
val mem : elt -> t -> bool
163-
val add : elt -> t -> t
164-
val singleton : elt -> t
165-
val remove : elt -> t -> t
166-
val union : t -> t -> t
167-
val inter : t -> t -> t
168-
val diff : t -> t -> t
169-
val compare : t -> t -> int
170-
val equal : t -> t -> bool
171-
val subset : t -> t -> bool
172-
val iter : (elt -> unit) -> t -> unit
173-
val fold : (elt -> 'a -> 'a) -> t -> 'a -> 'a
174-
val for_all : (elt -> bool) -> t -> bool
175-
val exists : (elt -> bool) -> t -> bool
176-
val filter : (elt -> bool) -> t -> t
177-
val partition : (elt -> bool) -> t -> t
178-
val cardinal : t -> int
179-
val elements : t -> elt list
180-
val min_elt : t -> elt
181-
val max_elt : t -> elt
182-
val choose : t -> elt
183-
end
184-
185152
(*
186153
* Linearly ordered set.
187154
*)

0 commit comments

Comments
 (0)