diff options
| author | Calvin <calvin@EESI> | 2013-03-15 15:26:20 -0400 | 
|---|---|---|
| committer | Calvin <calvin@EESI> | 2013-03-15 15:26:20 -0400 | 
| commit | b632667ce57af89691407bb8668e1512775278ae (patch) | |
| tree | b5742cef185f1cc4a7ba6005b5b4116ce7558a01 /src/nbc/tree.sml | |
| parent | 39e39f82cc38d71018882b0aaaf58255858a7c56 (diff) | |
nbc added
Diffstat (limited to 'src/nbc/tree.sml')
| -rw-r--r-- | src/nbc/tree.sml | 225 | 
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 | 
