(* vim: syntax=sml A structure implementing SET containers using simple binary search trees (BSTs). $Id: BstSet.sml,v 1.1 2004/09/09 21:15:11 cstork Exp $ Copyright (c) 2003-2004 by Peter H. Froehlich . All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. *) functor BstSet (Element: ORDERED): SET = struct type element = Element.t; (* A binary tree is either EMPTY or a NODE holding an element and two more binary trees (aka "left" and "right"). *) datatype set = EMPTY | NODE of Element.t * set * set; (* A new set is just the EMPTY binary tree. *) val new = EMPTY; (* An empty set is an EMPTY binary tree. *) fun empty (EMPTY) = true | empty (_) = false; (* Utility function to find minimum element. *) fun min (EMPTY) = raise Domain | min (NODE(v,EMPTY,_)) = v | min (NODE(v,l,_)) = min l; (* Utility function removing minimum element. *) fun remMin (EMPTY) = raise Domain | remMin (NODE(v,EMPTY,r)) = r | remMin (NODE(v,l,r)) = NODE(v, remMin l, r); (* TODO: min and remMin can be combined into one function. *) (* We insert into the binary tree "as usual" putting smaller elements to the left and larger elements to the right. If the element is already present, we don't change the tree. *) fun insert (EMPTY) e = NODE(e, EMPTY, EMPTY) | insert (n as NODE(v, l, r)) e = case (Element.compare e v) of EQUAL => n | LESS => NODE(v, (insert l e), r) | GREATER => NODE(v, l, (insert r e)); (* As for insert, we search the binary tree in the "usual" manner. *) fun has (EMPTY) e = false | has (NODE(v, l, r)) e = case (Element.compare e v) of EQUAL => true | LESS => has l e | GREATER => has r e; (* Again, we remove from the binary tree in the "usual" manner. Just in case, let me spell the algorithm out for you: Upon finding the element to delete, we first check whether it's left or right subtree are empty; in that case we can replace the element with it's subtree and are done. Otherwise we find the minimum element of the right subtree and replace the element to be removed with it (we could also use the maximum of the left subtree). Draw some pictures to see why this always works. *) fun remove (EMPTY) e = EMPTY | remove (NODE(v, l, r)) e = case (Element.compare e v) of EQUAL => if empty l then r else if empty r then l else let val min = min r; val rem = remMin r; in NODE(min, l, rem) end | LESS => NODE(v, (remove l e), r) | GREATER => NODE(v, l, (remove r e)); end; (* BstSet *)