mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			255 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Standard ML
		
	
	
	
	
	
			
		
		
	
	
			255 lines
		
	
	
		
			9.4 KiB
		
	
	
	
		
			Standard ML
		
	
	
	
	
	
(* From Twelf *)
 | 
						|
(* Red/Black Trees *)
 | 
						|
(* Author: Frank Pfenning *)
 | 
						|
 | 
						|
functor RedBlackTree
 | 
						|
  (type key'
 | 
						|
   val compare : key' * key' -> order)
 | 
						|
  :> TABLE where type key = key' =
 | 
						|
struct
 | 
						|
  type key = key'
 | 
						|
  type 'a entry = key * 'a
 | 
						|
 | 
						|
  datatype 'a dict =
 | 
						|
    Empty				(* considered black *)
 | 
						|
  | Red of 'a entry * 'a dict * 'a dict
 | 
						|
  | Black of 'a entry * 'a dict * 'a dict
 | 
						|
 | 
						|
  type 'a Table = 'a dict ref
 | 
						|
 | 
						|
  (* Representation Invariants *)
 | 
						|
  (*
 | 
						|
     1. The tree is ordered: for every node Red((key1,datum1), left, right) or
 | 
						|
        Black ((key1,datum1), left, right), every key in left is less than
 | 
						|
        key1 and every key in right is greater than key1.
 | 
						|
 | 
						|
     2. The children of a red node are black (color invariant).
 | 
						|
 | 
						|
     3. Every path from the root to a leaf has the same number of
 | 
						|
        black nodes, called the black height of the tree.
 | 
						|
  *)
 | 
						|
 | 
						|
  local
 | 
						|
 | 
						|
  fun lookup dict key =
 | 
						|
    let
 | 
						|
      fun lk (Empty) = NONE
 | 
						|
	| lk (Red tree) = lk' tree
 | 
						|
        | lk (Black tree) = lk' tree
 | 
						|
      and lk' ((key1, datum1), left, right) =
 | 
						|
	    (case compare(key,key1)
 | 
						|
	       of EQUAL => SOME(datum1)
 | 
						|
	        | LESS => lk left
 | 
						|
		| GREATER => lk right)
 | 
						|
      in
 | 
						|
	lk dict
 | 
						|
      end
 | 
						|
 | 
						|
  (* val restore_right : 'a dict -> 'a dict *)
 | 
						|
  (*
 | 
						|
     restore_right (Black(e,l,r)) >=> dict
 | 
						|
     where (1) Black(e,l,r) is ordered,
 | 
						|
           (2) Black(e,l,r) has black height n,
 | 
						|
	   (3) color invariant may be violated at the root of r:
 | 
						|
               one of its children might be red.
 | 
						|
     and dict is a re-balanced red/black tree (satisfying all invariants)
 | 
						|
     and same black height n.
 | 
						|
  *)
 | 
						|
  fun restore_right (Black(e, Red lt, Red (rt as (_,Red _,_)))) =
 | 
						|
         Red(e, Black lt, Black rt)	(* re-color *)
 | 
						|
    | restore_right (Black(e, Red lt, Red (rt as (_,_,Red _)))) =
 | 
						|
         Red(e, Black lt, Black rt)	(* re-color *)
 | 
						|
    | restore_right (Black(e, l, Red(re, Red(rle, rll, rlr), rr))) =
 | 
						|
	 (* l is black, deep rotate *)
 | 
						|
	 Black(rle, Red(e, l, rll), Red(re, rlr, rr))
 | 
						|
    | restore_right (Black(e, l, Red(re, rl, rr as Red _))) =
 | 
						|
	 (* l is black, shallow rotate *)
 | 
						|
	 Black(re, Red(e, l, rl), rr)
 | 
						|
    | restore_right dict = dict
 | 
						|
 | 
						|
  (* restore_left is like restore_right, except *)
 | 
						|
  (* the color invariant may be violated only at the root of left child *)
 | 
						|
  fun restore_left (Black(e, Red (lt as (_,Red _,_)), Red rt)) =
 | 
						|
	 Red(e, Black lt, Black rt)	(* re-color *)
 | 
						|
    | restore_left (Black(e, Red (lt as (_,_,Red _)), Red rt)) =
 | 
						|
	 Red(e, Black lt, Black rt)	(* re-color *)
 | 
						|
    | restore_left (Black(e, Red(le, ll as Red _, lr), r)) =
 | 
						|
	 (* r is black, shallow rotate *)
 | 
						|
	 Black(le, ll, Red(e, lr, r))
 | 
						|
    | restore_left (Black(e, Red(le, ll, Red(lre, lrl, lrr)), r)) =
 | 
						|
	 (* r is black, deep rotate *)
 | 
						|
	 Black(lre, Red(le, ll, lrl), Red(e, lrr, r))
 | 
						|
    | restore_left dict = dict
 | 
						|
 | 
						|
  fun insert (dict, entry as (key,datum)) =
 | 
						|
    let
 | 
						|
      (* val ins : 'a dict -> 'a dict  inserts entry *)
 | 
						|
      (* ins (Red _) may violate color invariant at root *)
 | 
						|
      (* ins (Black _) or ins (Empty) will be red/black tree *)
 | 
						|
      (* ins preserves black height *)
 | 
						|
      fun ins (Empty) = Red(entry, Empty, Empty)
 | 
						|
	| ins (Red(entry1 as (key1, datum1), left, right)) =
 | 
						|
	  (case compare(key,key1)
 | 
						|
	     of EQUAL => Red(entry, left, right)
 | 
						|
	      | LESS => Red(entry1, ins left, right)
 | 
						|
	      | GREATER => Red(entry1, left, ins right))
 | 
						|
	| ins (Black(entry1 as (key1, datum1), left, right)) =
 | 
						|
	  (case compare(key,key1)
 | 
						|
	     of EQUAL => Black(entry, left, right)
 | 
						|
	      | LESS => restore_left (Black(entry1, ins left, right))
 | 
						|
	      | GREATER => restore_right (Black(entry1, left, ins right)))
 | 
						|
    in
 | 
						|
      case ins dict
 | 
						|
	of Red (t as (_, Red _, _)) => Black t (* re-color *)
 | 
						|
	 | Red (t as (_, _, Red _)) => Black t (* re-color *)
 | 
						|
	 | dict => dict
 | 
						|
    end
 | 
						|
 | 
						|
  (* function below from .../smlnj-lib/Util/int-redblack-set.sml *)
 | 
						|
  (* Need to check and improve some time *)
 | 
						|
  (* Sun Mar 13 08:22:53 2005 -fp *)
 | 
						|
 | 
						|
  (* Remove an item.  Returns true if old item found, false otherwise *)
 | 
						|
    local
 | 
						|
      exception NotFound
 | 
						|
      datatype 'a zipper
 | 
						|
	= TOP
 | 
						|
	| LEFTB of ('a entry * 'a dict * 'a zipper)
 | 
						|
	| LEFTR of ('a entry * 'a dict * 'a zipper)
 | 
						|
	| RIGHTB of ('a dict * 'a entry * 'a zipper)
 | 
						|
	| RIGHTR of ('a dict * 'a entry * 'a zipper)
 | 
						|
    in
 | 
						|
    fun delete t key =
 | 
						|
        let
 | 
						|
	  fun zip (TOP, t) = t
 | 
						|
	    | zip (LEFTB(x, b, z), a) = zip(z, Black(x, a, b))
 | 
						|
	    | zip (LEFTR(x, b, z), a) = zip(z, Red(x, a, b))
 | 
						|
	    | zip (RIGHTB(a, x, z), b) = zip(z, Black(x, a, b))
 | 
						|
	    | zip (RIGHTR(a, x, z), b) = zip(z, Red(x, a, b))
 | 
						|
	(* bbZip propagates a black deficit up the tree until either the top
 | 
						|
	 * is reached, or the deficit can be covered.  It returns a boolean
 | 
						|
	 * that is true if there is still a deficit and the zipped tree.
 | 
						|
	 *)
 | 
						|
	  fun bbZip (TOP, t) = (true, t)
 | 
						|
	    | bbZip (LEFTB(x, Red(y, c, d), z), a) = (* case 1L *)
 | 
						|
		bbZip (LEFTR(x, c, LEFTB(y, d, z)), a)
 | 
						|
	    | bbZip (LEFTB(x, Black(w, Red(y, c, d), e), z), a) = (* case 3L *)
 | 
						|
		bbZip (LEFTB(x, Black(y, c, Red(w, d, e)), z), a)
 | 
						|
	    | bbZip (LEFTR(x, Black(w, Red(y, c, d), e), z), a) = (* case 3L *)
 | 
						|
		bbZip (LEFTR(x, Black(y, c, Red(w, d, e)), z), a)
 | 
						|
	    | bbZip (LEFTB(x, Black(y, c, Red(w, d, e)), z), a) = (* case 4L *)
 | 
						|
		(false, zip (z, Black(y, Black(x, a, c), Black(w, d, e))))
 | 
						|
	    | bbZip (LEFTR(x, Black(y, c, Red(w, d, e)), z), a) = (* case 4L *)
 | 
						|
		(false, zip (z, Red(y, Black(x, a, c), Black(w, d, e))))
 | 
						|
	    | bbZip (LEFTR(x, Black(y, c, d), z), a) = (* case 2L *)
 | 
						|
		(false, zip (z, Black(x, a, Red(y, c, d))))
 | 
						|
	    | bbZip (LEFTB(x, Black(y, c, d), z), a) = (* case 2L *)
 | 
						|
		bbZip (z, Black(x, a, Red(y, c, d)))
 | 
						|
	    | bbZip (RIGHTB(Red(y, c, d), x, z), b) = (* case 1R *)
 | 
						|
		bbZip (RIGHTR(d, x, RIGHTB(c, y, z)), b)
 | 
						|
	    | bbZip (RIGHTR(Red(y, c, d), x, z), b) = (* case 1R *)
 | 
						|
		bbZip (RIGHTR(d, x, RIGHTB(c, y, z)), b)
 | 
						|
	    | bbZip (RIGHTB(Black(y, Red(w, c, d), e), x, z), b) = (* case 3R *)
 | 
						|
		bbZip (RIGHTB(Black(w, c, Red(y, d, e)), x, z), b)
 | 
						|
	    | bbZip (RIGHTR(Black(y, Red(w, c, d), e), x, z), b) = (* case 3R *)
 | 
						|
		bbZip (RIGHTR(Black(w, c, Red(y, d, e)), x, z), b)
 | 
						|
	    | bbZip (RIGHTB(Black(y, c, Red(w, d, e)), x, z), b) = (* case 4R *)
 | 
						|
		(false, zip (z, Black(y, c, Black(x, Red(w, d, e), b))))
 | 
						|
	    | bbZip (RIGHTR(Black(y, c, Red(w, d, e)), x, z), b) = (* case 4R *)
 | 
						|
		(false, zip (z, Red(y, c, Black(w, Red(w, d, e), b))))
 | 
						|
	    | bbZip (RIGHTR(Black(y, c, d), x, z), b) = (* case 2R *)
 | 
						|
		(false, zip (z, Black(x, Red(y, c, d), b)))
 | 
						|
	    | bbZip (RIGHTB(Black(y, c, d), x, z), b) = (* case 2R *)
 | 
						|
		bbZip (z, Black(x, Red(y, c, d), b))
 | 
						|
	    | bbZip (z, t) = (false, zip(z, t))
 | 
						|
	  fun delMin (Red(y, Empty, b), z) = (y, (false, zip(z, b)))
 | 
						|
	    | delMin (Black(y, Empty, b), z) = (y, bbZip(z, b))
 | 
						|
	    | delMin (Black(y, a, b), z) = delMin(a, LEFTB(y, b, z))
 | 
						|
	    | delMin (Red(y, a, b), z) = delMin(a, LEFTR(y, b, z))
 | 
						|
	    | delMin (Empty, _) = raise Match
 | 
						|
	  fun joinRed (Empty, Empty, z) = zip(z, Empty)
 | 
						|
	    | joinRed (a, b, z) = let
 | 
						|
		val (x, (needB, b')) = delMin(b, TOP)
 | 
						|
		in
 | 
						|
		  if needB
 | 
						|
		    then #2(bbZip(z, Red(x, a, b')))
 | 
						|
		    else zip(z, Red(x, a, b'))
 | 
						|
		end
 | 
						|
	  fun joinBlack (a, Empty, z) = #2(bbZip(z, a))
 | 
						|
	    | joinBlack (Empty, b, z) = #2(bbZip(z, b))
 | 
						|
	    | joinBlack (a, b, z) = let
 | 
						|
		val (x, (needB, b')) = delMin(b, TOP)
 | 
						|
		in
 | 
						|
		  if needB
 | 
						|
		    then #2(bbZip(z, Black(x, a, b')))
 | 
						|
		    else zip(z, Black(x, a, b'))
 | 
						|
		end
 | 
						|
	  fun del (Empty, z) = raise NotFound
 | 
						|
	    | del (Black(entry1 as (key1, datum1), a, b), z) =
 | 
						|
	      (case compare(key,key1)
 | 
						|
		 of EQUAL => joinBlack (a, b, z)
 | 
						|
                  | LESS => del (a, LEFTB(entry1, b, z))
 | 
						|
		  | GREATER => del (b, RIGHTB(a, entry1, z)))
 | 
						|
	    | del (Red(entry1 as (key1, datum1), a, b), z) =
 | 
						|
	      (case compare(key,key1)
 | 
						|
                 of EQUAL => joinRed (a, b, z)
 | 
						|
                  | LESS => del (a, LEFTR(entry1, b, z))
 | 
						|
                  | GREATER => del (b, RIGHTR(a, entry1, z)))
 | 
						|
	  in
 | 
						|
	    (del(t, TOP); true) handle NotFound => false
 | 
						|
	  end
 | 
						|
    end (* local *)
 | 
						|
 | 
						|
  (* use non-imperative version? *)
 | 
						|
  fun insertShadow (dict, entry as (key,datum)) =
 | 
						|
      let val oldEntry = ref NONE (* : 'a entry option ref *)
 | 
						|
          fun ins (Empty) = Red(entry, Empty, Empty)
 | 
						|
	    | ins (Red(entry1 as (key1, datum1), left, right)) =
 | 
						|
	      (case compare(key,key1)
 | 
						|
		 of EQUAL => (oldEntry := SOME(entry1);
 | 
						|
			      Red(entry, left, right))
 | 
						|
	          | LESS => Red(entry1, ins left, right)
 | 
						|
	          | GREATER => Red(entry1, left, ins right))
 | 
						|
	    | ins (Black(entry1 as (key1, datum1), left, right)) =
 | 
						|
	      (case compare(key,key1)
 | 
						|
		 of EQUAL => (oldEntry := SOME(entry1);
 | 
						|
			      Black(entry, left, right))
 | 
						|
	          | LESS => restore_left (Black(entry1, ins left, right))
 | 
						|
	          | GREATER => restore_right (Black(entry1, left, ins right)))
 | 
						|
      in
 | 
						|
	(oldEntry := NONE;
 | 
						|
	 ((case ins dict
 | 
						|
	     of Red (t as (_, Red _, _)) => Black t (* re-color *)
 | 
						|
	      | Red (t as (_, _, Red _)) => Black t (* re-color *)
 | 
						|
	      | dict => dict),
 | 
						|
	  !oldEntry))
 | 
						|
      end
 | 
						|
  
 | 
						|
  fun app f dict =
 | 
						|
      let fun ap (Empty) = ()
 | 
						|
	    | ap (Red tree) = ap' tree
 | 
						|
	    | ap (Black tree) = ap' tree
 | 
						|
	  and ap' (entry1, left, right) =
 | 
						|
	      (ap left; f entry1; ap right)
 | 
						|
      in
 | 
						|
	ap dict
 | 
						|
      end
 | 
						|
 | 
						|
  in
 | 
						|
    fun new (n) = ref (Empty) (* ignore size hint *)
 | 
						|
    val insert = (fn table => fn entry => (table := insert (!table, entry)))
 | 
						|
    val insertShadow =
 | 
						|
        (fn table => fn entry => 
 | 
						|
	 let
 | 
						|
	   val (dict, oldEntry) = insertShadow (!table, entry)
 | 
						|
	 in
 | 
						|
	   (table := dict; oldEntry)
 | 
						|
	 end)
 | 
						|
    val lookup = (fn table => fn key => lookup (!table) key)
 | 
						|
    val delete = (fn table => fn key => (delete (!table) key; ()))
 | 
						|
    val clear = (fn table => (table := Empty))
 | 
						|
    val app = (fn f => fn table => app f (!table))
 | 
						|
  end
 | 
						|
 | 
						|
end;  (* functor RedBlackTree *)
 |