home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-08-18 | 7.5 KB | 223 lines | [TEXT/R*ch] |
- (* Splayset -- modified for Moscow ML 1995-04-22
- * from SML/NJ library v. 0.2
- *
- * COPYRIGHT (c) 1993 by AT&T Bell Laboratories.
- * See file mosml/copyrght/copyrght.att for details.
- *
- * Set of values with an ordering relation, implemented as splay-trees.
- *)
-
- open Splaytree
-
- datatype 'key set =
- OS of {cmpKey : 'key * 'key -> order,
- root : 'key splay ref,
- nobj : int}
-
- exception NotFound
- fun cmpf cmpKey k = fn k' => cmpKey(k',k)
-
- fun empty cmpKey = OS{cmpKey = cmpKey, root = ref SplayNil, nobj = 0}
-
- fun singleton cmpKey v =
- OS{cmpKey= cmpKey,
- root = ref(SplayObj{value=v,left=SplayNil,right=SplayNil}),
- nobj=1}
-
- (* Primitive insertion. *)
- fun insert cmpKey (v,(nobj,root)) =
- case splay (cmpf cmpKey v, root) of
- (_,SplayNil) =>
- (1,SplayObj{value=v,left=SplayNil,right=SplayNil})
- | (EQUAL,SplayObj{value,left,right}) =>
- (nobj,SplayObj{value=v,left=left,right=right})
- | (LESS,SplayObj{value,left,right}) =>
- (nobj+1,
- SplayObj{
- value=v,
- left=SplayObj{value=value,left=left,right=SplayNil},
- right=right})
- | (GREATER,SplayObj{value,left,right}) =>
- (nobj+1,
- SplayObj{
- value=v,
- left=left,
- right=SplayObj{value=value,left=SplayNil,right=right}})
-
- (* Add an item. *)
- fun add (OS{cmpKey,root,nobj},v) = let
- val (cnt,t) = insert cmpKey (v,(nobj,!root))
- in
- OS{cmpKey=cmpKey, nobj=cnt, root=ref t}
- end
-
- (* Insert a list of items. *)
- fun addList (OS{cmpKey,root,nobj},l) = let
- val (cnt,t) = List.foldl (insert cmpKey) (nobj,!root) l
- in OS{cmpKey=cmpKey, nobj=cnt, root=ref t} end
-
- (* Look for an item, return NONE if the item doesn't exist *)
- fun peek (d as OS{cmpKey,root,nobj}, key) =
- case splay (cmpf cmpKey key, !root) of
- (_,SplayNil) => NONE
- | (EQUAL,r as SplayObj{value,...}) => (root := r; SOME value)
- | (_,r) => (root := r; NONE)
-
- (* Find an item *)
- fun member arg = case peek arg of NONE => false | SOME _ => true
-
- (* Find an item, raising NotFound if not found *)
- fun retrieve arg = case peek arg of NONE => raise NotFound | SOME v => v
-
- (* Remove an item.
- * Raise NotFound if not found
- *)
- fun delete (OS{cmpKey,root,nobj},key) =
- case splay (cmpf cmpKey key, !root) of
- (_,SplayNil) => raise NotFound
- | (EQUAL,SplayObj{value,left,right}) =>
- OS{cmpKey=cmpKey, root=ref(join(left,right)), nobj=nobj-1}
- | (_,r) => (root := r; raise NotFound)
-
- (* Return the number of items in the table *)
- fun numItems (OS{nobj,...}) = nobj
-
- fun isEmpty (OS{nobj=0,...}) = true
- | isEmpty _ = false
-
- local
- fun member cmpKey (x,tree) = let
- fun mbr SplayNil = false
- | mbr (SplayObj{value,left,right}) =
- case cmpKey (x,value) of
- LESS => mbr left
- | GREATER => mbr right
- | _ => true
- in mbr tree end
-
- (* true if every item in t is in t' *)
- fun treeIn cmpKey (t,t') = let
- fun isIn SplayNil = true
- | isIn (SplayObj{value,left=SplayNil,right=SplayNil}) =
- member cmpKey (value, t')
- | isIn (SplayObj{value,left,right=SplayNil}) =
- member cmpKey (value, t') andalso isIn left
- | isIn (SplayObj{value,left=SplayNil,right}) =
- member cmpKey (value, t') andalso isIn right
- | isIn (SplayObj{value,left,right}) =
- member cmpKey (value, t') andalso isIn left andalso isIn right
- in
- isIn t
- end
- in
- fun isSubset (OS{cmpKey,root=rt,nobj=n},OS{root=rt',nobj=n',...}) =
- n<=n' andalso treeIn cmpKey (!rt,!rt');
-
- fun equal (OS{cmpKey,root=rt,nobj=n},OS{root=rt',nobj=n',...}) =
- n=n' andalso treeIn cmpKey (!rt,!rt');
- end
-
- fun split cmpKey value s =
- case splay(cmpf cmpKey value, s) of
- (EQUAL,SplayObj{value,left,right}) => (SOME value, left, right)
- | (LESS,SplayObj{value,left,right}) => (NONE, SplayObj{value=value,left=left,right=SplayNil},right)
- | (GREATER,SplayObj{value,left,right}) => (NONE, left, SplayObj{value=value,right=right,left=SplayNil})
- | (_,SplayNil) => (NONE, SplayNil, SplayNil)
-
- fun intersection (s as OS{nobj=0,...},_) = s
- | intersection (_,s as OS{nobj=0,...}) = s
- | intersection (OS{cmpKey,root,...},OS{root=root',...}) =
- let fun inter SplayNil _ = (SplayNil,0)
- | inter _ SplayNil = (SplayNil,0)
- | inter s (SplayObj{value,left,right}) =
- case split cmpKey value s of
- (SOME v, l, r) =>
- let val (l',lcnt) = inter l left
- val (r',rcnt) = inter r right
- in (SplayObj{value=v,left=l',right=r'},lcnt+rcnt+1) end
- | (_,l,r) =>
- let val (l',lcnt) = inter l left
- val (r',rcnt) = inter r right
- in (join(l',r'),lcnt+rcnt) end
- val (root,cnt) = inter (!root) (!root')
- in OS{cmpKey = cmpKey, root = ref root, nobj = cnt} end
-
- fun count st =
- let fun cnt SplayNil n = n
- | cnt (SplayObj{left,right,...}) n = cnt left (cnt right (n+1))
- in cnt st 0 end
-
- fun difference (s as OS{nobj=0,...},_) = s
- | difference (s,OS{nobj=0,...}) = s
- | difference (OS{cmpKey, root,...}, OS{root=root',...}) =
- let fun diff SplayNil _ = (SplayNil,0)
- | diff s SplayNil = (s, count s)
- | diff s (SplayObj{value,right,left}) =
- let val (_,l,r) = split cmpKey value s
- val (l',lcnt) = diff l left
- val (r',rcnt) = diff r right
- in (join(l',r'),lcnt+rcnt) end
- val (root,cnt) = diff (!root) (!root')
- in OS{cmpKey = cmpKey, root = ref root, nobj = cnt} end
-
- fun union (OS{nobj=0,...},s) = s
- | union (s,OS{nobj=0,...}) = s
- | union (OS{cmpKey, root,...}, OS{root=root',...}) =
- let fun uni SplayNil s = (s,count s)
- | uni s SplayNil = (s, count s)
- | uni s (SplayObj{value,right,left}) =
- let val (_,l,r) = split cmpKey value s
- val (l',lcnt) = uni l left
- val (r',rcnt) = uni r right
- in
- (SplayObj{value=value,right=r',left=l'},lcnt+rcnt+1)
- end
- val (root,cnt) = uni (!root) (!root')
- in
- OS{cmpKey = cmpKey, root = ref root, nobj = cnt}
- end
-
- (* Return a list of the items (and their keys) in the dictionary *)
- fun listItems (OS{root,...}) =
- let fun apply SplayNil res = res
- | apply (SplayObj{value,left,right}) res =
- apply left (value :: apply right res)
- in apply (!root) [] end
-
- (* Apply a function to the entries of the dictionary *)
- fun app af (OS{root,...}) =
- let fun apply SplayNil = ()
- | apply (SplayObj{value,left,right}) =
- (apply left; af value; apply right)
- in
- apply (!root)
- end
-
- fun revapp af (OS{root,...}) =
- let fun apply SplayNil = ()
- | apply (SplayObj{value,left,right}) =
- (apply right; af value; apply left)
- in apply (!root) end
-
- (* Fold function *)
- fun foldr abf b (OS{root,...}) =
- let fun apply SplayNil res = res
- | apply (SplayObj{value,left,right}) res =
- apply left (abf(value, apply right res))
- in apply (!root) b end
-
- fun foldl abf b (OS{root,...}) =
- let fun apply SplayNil res = res
- | apply (SplayObj{value,left,right}) res =
- apply right (abf(value, apply left b))
- in apply (!root) b end
-
- fun find p (OS{root,...}) =
- let fun ex SplayNil = NONE
- | ex (SplayObj{value=v,left=l,right=r}) =
- if p v then SOME v
- else case ex l of
- NONE => ex r
- | a => a
- in ex (!root) end
-