summaryrefslogtreecommitdiff
path: root/src/nbc/tree.sml
diff options
context:
space:
mode:
authorCalvin <calvin@EESI>2013-03-15 15:26:20 -0400
committerCalvin <calvin@EESI>2013-03-15 15:26:20 -0400
commitb632667ce57af89691407bb8668e1512775278ae (patch)
treeb5742cef185f1cc4a7ba6005b5b4116ce7558a01 /src/nbc/tree.sml
parent39e39f82cc38d71018882b0aaaf58255858a7c56 (diff)
nbc added
Diffstat (limited to 'src/nbc/tree.sml')
-rw-r--r--src/nbc/tree.sml225
1 files changed, 225 insertions, 0 deletions
diff --git a/src/nbc/tree.sml b/src/nbc/tree.sml
new file mode 100644
index 0000000..5d64f51
--- /dev/null
+++ b/src/nbc/tree.sml
@@ -0,0 +1,225 @@
+functor Tree (Key: sig
+ type key
+ val compare: key * key -> order
+end) :> sig
+ type key = Key.key
+ type 'datum tree
+ val size: 'datum tree -> int
+ val empty: 'datum tree
+ val single: key * 'datum -> 'datum tree
+ val add: 'datum tree * key * 'datum -> 'datum tree
+ val find: 'datum tree * key -> 'datum option
+ val exists: 'datum tree * key -> bool
+ val up: 'datum tree -> (key * 'datum) Stream.stream
+ val down: 'datum tree -> (key * 'datum) Stream.stream
+ val upFrom: 'datum tree * key -> (key * 'datum) Stream.stream
+ val downFrom: 'datum tree * key -> (key * 'datum) Stream.stream
+ val fromList: (key * 'datum) list -> 'datum tree
+ val fromStream: (key * 'datum) Stream.stream -> 'datum tree
+ (*
+ val remove: 'datum tree * key -> 'datum tree
+ *)
+end = struct
+ type key = Key.key
+ structure Height = Int8
+ datatype 'datum tree =
+ Leaf
+ | Branch of {
+ height: Height.int
+ , less: 'datum tree
+ , key: key
+ , datum: 'datum
+ , greater: 'datum tree
+ }
+ fun size tree = case tree of
+ Leaf => 0
+ | Branch {less, greater, ...} =>
+ 1 + size less + size greater
+ val empty = Leaf
+ fun single (key, datum) = Branch {
+ height = 1
+ , less = Leaf
+ , key = key
+ , datum = datum
+ , greater = Leaf
+ }
+ fun height tree = case tree of
+ Leaf => 0
+ | Branch {height, ...} => height
+ fun calculateHeight {key, datum, less, greater} = Branch {
+ key = key
+ , datum = datum
+ , less = less
+ , greater = greater
+ , height = 1 + Height.max (height less, height greater)
+ }
+ fun rotateLess branch = case branch of
+ (*
+ b d
+ a d => b e
+ c e a c
+ *)
+ {
+ less = a
+ , key = bKey
+ , datum = bDatum
+ , greater = Branch {
+ less = c
+ , key = dKey
+ , datum = dDatum
+ , greater = e
+ , height = _
+ }
+ } => calculateHeight {
+ less = calculateHeight {
+ less = a
+ , key = bKey
+ , datum = bDatum
+ , greater = c
+ }, key = dKey
+ , datum = dDatum
+ , greater = e
+ } | _ => raise Fail "rotateLess"
+ fun rotateGreater branch = case branch of
+ (*
+ d b
+ b e => a d
+ a c c e
+ *)
+ {
+ less = Branch {
+ less = a
+ , key = bKey
+ , datum = bDatum
+ , greater = c
+ , height = _
+ }, key = dKey
+ , datum = dDatum
+ , greater = e
+ } => calculateHeight {
+ less = a
+ , key = bKey
+ , datum = bDatum
+ , greater = calculateHeight {
+ less = c
+ , key = dKey
+ , datum = dDatum
+ , greater = e
+ }
+ } | _ => raise Fail "rotateGreater"
+ fun balance (branch as {key, datum, less, greater}) =
+ let
+ val heightLess = height less
+ val heightGreater = height greater
+ in
+ if heightLess < heightGreater - 2 then
+ rotateLess branch
+ else if heightLess > heightGreater + 2 then
+ rotateGreater branch
+ else calculateHeight branch
+ end
+ fun add (tree, newKey, newDatum) = case tree of
+ Leaf => single (newKey, newDatum)
+ | Branch {height, less, key, datum, greater} =>
+ case Key.compare (newKey, key) of
+ EQUAL => Branch {
+ height = height
+ , less = less
+ , key = newKey
+ , datum = newDatum
+ , greater = greater
+ } | LESS => balance {
+ less = add (less, newKey, newDatum)
+ , key = key
+ , datum = datum
+ , greater = greater
+ } | GREATER => balance {
+ less = less
+ , key = key
+ , datum = datum
+ , greater = add (greater, newKey, newDatum)
+ }
+ fun find (tree, desiredKey) = case tree of
+ Leaf => NONE
+ | Branch {less, key, datum, greater, ...} =>
+ case Key.compare (desiredKey, key) of
+ EQUAL => SOME datum
+ | LESS => find (less, desiredKey)
+ | GREATER => find (greater, desiredKey)
+ fun exists (tree, desiredKey) = case find (tree, desiredKey) of
+ NONE => false
+ | SOME _ => true
+ fun up tree = Stream.create (fn () =>
+ case tree of
+ Leaf => NONE
+ | Branch {less, key, datum, greater, ...} =>
+ Stream.getItem (
+ Stream.append (
+ up less
+ , Stream.cons (
+ (key, datum)
+ , up greater
+ )
+ )
+ )
+ )
+ fun down tree = Stream.create (fn () =>
+ case tree of
+ Leaf => NONE
+ | Branch {greater, key, datum, less, ...} =>
+ Stream.getItem (
+ Stream.append (
+ down greater
+ , Stream.cons (
+ (key, datum)
+ , down less
+ )
+ )
+ )
+ )
+ fun upFrom (tree, firstKey) = Stream.create (fn () =>
+ case tree of
+ Leaf => NONE
+ | Branch {less, key, datum, greater, ...} =>
+ case Key.compare (firstKey, key) of
+ LESS => Stream.getItem (
+ Stream.append (
+ upFrom (less, firstKey)
+ , Stream.cons (
+ (key, datum)
+ , up greater
+ )
+ )
+ ) | EQUAL => SOME (
+ (key, datum)
+ , up greater
+ ) | GREATER => Stream.getItem (
+ upFrom (greater, firstKey)
+ )
+ )
+ fun downFrom (tree, firstKey) = Stream.create (fn () =>
+ case tree of
+ Leaf => NONE
+ | Branch {greater, key, datum, less, ...} =>
+ case Key.compare (firstKey, key) of
+ LESS => Stream.getItem (
+ downFrom (less, firstKey)
+ ) | EQUAL => SOME (
+ (key, datum)
+ , down less
+ ) | GREATER => Stream.getItem (
+ Stream.append (
+ downFrom (greater, firstKey)
+ , Stream.cons (
+ (key, datum)
+ , down less
+ )
+ )
+ )
+ )
+ fun fromStream stream =
+ Stream.fold (fn ((key, datum), tree) =>
+ add (tree, key, datum)
+ ) empty stream
+ fun fromList list = fromStream (Stream.fromList list)
+end