赤黒木
赤黒木のinsertをOCamlで書きました.
removeはもっと全然面倒で, 書いてはみたけどデバッグに途方に暮れ挫折しました.
module type OrderedType = sig type t val compare : t -> t -> int end module Make(Ord : OrderedType) = struct type elt = Ord.t type t = R of t * elt * t | B of t * elt * t | Nil let is_black = function | R _ -> false | _ -> true (* [insert e tree] inserts [e] into [tree] and returns it. If any element [e'] exists and [Ord.compare e e' = 0] is true, it does nothing. *) let insert e tree = let rec ins e = function | Nil -> R (Nil, e, Nil) | R (l, e', r) -> (match Ord.compare e e' with | 0 -> R (l, e, r) | b when b > 0 -> R (l, e', ins e r) | b when b < 0 -> R (ins e l, e', r) | _ -> assert false) | B (l, e', r) -> let rec fixr = function | B (R (ly, y, ry), w, R (lz, z, R (lx, x, rx))) -> R (B (ly, y, ry), w, B (lz, z, R (lx, x, rx))) | B (y, w, R (lz, z, R (lx, x, rx))) when is_black y -> B (R (y, w, lz), z, R (lx, x, rx)) | B (lw, w, R (R (lx, x, rx), z, rz)) -> fixr (B (lw, w, R (lx, x, R (rx, z, rz)))) | x -> x in let rec fixl = function | B (R (R (lx, x, rx), z, rz), w, R (ly, y, ry)) -> R (B (R (lx, x, rx), z, rz), w, B (ly, y, ry)) | B (R (R (lx, x, rx), z, rz), w, y) when is_black y -> B (R (lx, x, rx), z, R (rz, w, y)) | B (R (lz, z, R (lx, x, rx)), w, rw) -> fixl (B (R (R (lz, z, lx), x, rx), w, rw)) | x -> x in (match Ord.compare e e' with | 0 -> B (l, e, r) | b when b > 0 -> fixr (B (l, e', ins e r)) | b when b < 0 -> fixl (B (ins e l, e', r)) | _ -> assert false) in match ins e tree with | R (l, e, r) | B (l, e, r) -> B (l, e, r) | Nil -> assert false end
これでもそれなりに気分良く書けて満足してたんだけど, 世の中はとんでもなく進んでいて, http://tinyurl.com/yqrr6pとかうーん. 場合分けの数が極端に少ないなあ. どうなってんの?
ちなみにいつものように赤黒木の実装で参考にしたのはamazon:Introduction to Algorithmsで紹介されているもの.