| // Copyright 2010 Petar Maymounkov. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // A Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary search trees, |
| // based on the following work: |
| // |
| // http://www.cs.princeton.edu/~rs/talks/LLRB/08Penn.pdf |
| // http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf |
| // http://www.cs.princeton.edu/~rs/talks/LLRB/Java/RedBlackBST.java |
| // |
| // 2-3 trees (and the run-time equivalent 2-3-4 trees) are the de facto standard BST |
| // algoritms found in implementations of Python, Java, and other libraries. The LLRB |
| // implementation of 2-3 trees is a recent improvement on the traditional implementation, |
| // observed and documented by Robert Sedgewick. |
| // |
| package llrb |
| |
| // Tree is a Left-Leaning Red-Black (LLRB) implementation of 2-3 trees |
| type LLRB struct { |
| count int |
| root *Node |
| } |
| |
| type Node struct { |
| Item |
| Left, Right *Node // Pointers to left and right child nodes |
| Black bool // If set, the color of the link (incoming from the parent) is black |
| // In the LLRB, new nodes are always red, hence the zero-value for node |
| } |
| |
| type Item interface { |
| Less(than Item) bool |
| } |
| |
| // |
| func less(x, y Item) bool { |
| if x == pinf { |
| return false |
| } |
| if x == ninf { |
| return true |
| } |
| return x.Less(y) |
| } |
| |
| // Inf returns an Item that is "bigger than" any other item, if sign is positive. |
| // Otherwise it returns an Item that is "smaller than" any other item. |
| func Inf(sign int) Item { |
| if sign == 0 { |
| panic("sign") |
| } |
| if sign > 0 { |
| return pinf |
| } |
| return ninf |
| } |
| |
| var ( |
| ninf = nInf{} |
| pinf = pInf{} |
| ) |
| |
| type nInf struct{} |
| |
| func (nInf) Less(Item) bool { |
| return true |
| } |
| |
| type pInf struct{} |
| |
| func (pInf) Less(Item) bool { |
| return false |
| } |
| |
| // New() allocates a new tree |
| func New() *LLRB { |
| return &LLRB{} |
| } |
| |
| // SetRoot sets the root node of the tree. |
| // It is intended to be used by functions that deserialize the tree. |
| func (t *LLRB) SetRoot(r *Node) { |
| t.root = r |
| } |
| |
| // Root returns the root node of the tree. |
| // It is intended to be used by functions that serialize the tree. |
| func (t *LLRB) Root() *Node { |
| return t.root |
| } |
| |
| // Len returns the number of nodes in the tree. |
| func (t *LLRB) Len() int { return t.count } |
| |
| // Has returns true if the tree contains an element whose order is the same as that of key. |
| func (t *LLRB) Has(key Item) bool { |
| return t.Get(key) != nil |
| } |
| |
| // Get retrieves an element from the tree whose order is the same as that of key. |
| func (t *LLRB) Get(key Item) Item { |
| h := t.root |
| for h != nil { |
| switch { |
| case less(key, h.Item): |
| h = h.Left |
| case less(h.Item, key): |
| h = h.Right |
| default: |
| return h.Item |
| } |
| } |
| return nil |
| } |
| |
| // Min returns the minimum element in the tree. |
| func (t *LLRB) Min() Item { |
| h := t.root |
| if h == nil { |
| return nil |
| } |
| for h.Left != nil { |
| h = h.Left |
| } |
| return h.Item |
| } |
| |
| // Max returns the maximum element in the tree. |
| func (t *LLRB) Max() Item { |
| h := t.root |
| if h == nil { |
| return nil |
| } |
| for h.Right != nil { |
| h = h.Right |
| } |
| return h.Item |
| } |
| |
| func (t *LLRB) ReplaceOrInsertBulk(items ...Item) { |
| for _, i := range items { |
| t.ReplaceOrInsert(i) |
| } |
| } |
| |
| func (t *LLRB) InsertNoReplaceBulk(items ...Item) { |
| for _, i := range items { |
| t.InsertNoReplace(i) |
| } |
| } |
| |
| // ReplaceOrInsert inserts item into the tree. If an existing |
| // element has the same order, it is removed from the tree and returned. |
| func (t *LLRB) ReplaceOrInsert(item Item) Item { |
| if item == nil { |
| panic("inserting nil item") |
| } |
| var replaced Item |
| t.root, replaced = t.replaceOrInsert(t.root, item) |
| t.root.Black = true |
| if replaced == nil { |
| t.count++ |
| } |
| return replaced |
| } |
| |
| func (t *LLRB) replaceOrInsert(h *Node, item Item) (*Node, Item) { |
| if h == nil { |
| return newNode(item), nil |
| } |
| |
| h = walkDownRot23(h) |
| |
| var replaced Item |
| if less(item, h.Item) { // BUG |
| h.Left, replaced = t.replaceOrInsert(h.Left, item) |
| } else if less(h.Item, item) { |
| h.Right, replaced = t.replaceOrInsert(h.Right, item) |
| } else { |
| replaced, h.Item = h.Item, item |
| } |
| |
| h = walkUpRot23(h) |
| |
| return h, replaced |
| } |
| |
| // InsertNoReplace inserts item into the tree. If an existing |
| // element has the same order, both elements remain in the tree. |
| func (t *LLRB) InsertNoReplace(item Item) { |
| if item == nil { |
| panic("inserting nil item") |
| } |
| t.root = t.insertNoReplace(t.root, item) |
| t.root.Black = true |
| t.count++ |
| } |
| |
| func (t *LLRB) insertNoReplace(h *Node, item Item) *Node { |
| if h == nil { |
| return newNode(item) |
| } |
| |
| h = walkDownRot23(h) |
| |
| if less(item, h.Item) { |
| h.Left = t.insertNoReplace(h.Left, item) |
| } else { |
| h.Right = t.insertNoReplace(h.Right, item) |
| } |
| |
| return walkUpRot23(h) |
| } |
| |
| // Rotation driver routines for 2-3 algorithm |
| |
| func walkDownRot23(h *Node) *Node { return h } |
| |
| func walkUpRot23(h *Node) *Node { |
| if isRed(h.Right) && !isRed(h.Left) { |
| h = rotateLeft(h) |
| } |
| |
| if isRed(h.Left) && isRed(h.Left.Left) { |
| h = rotateRight(h) |
| } |
| |
| if isRed(h.Left) && isRed(h.Right) { |
| flip(h) |
| } |
| |
| return h |
| } |
| |
| // Rotation driver routines for 2-3-4 algorithm |
| |
| func walkDownRot234(h *Node) *Node { |
| if isRed(h.Left) && isRed(h.Right) { |
| flip(h) |
| } |
| |
| return h |
| } |
| |
| func walkUpRot234(h *Node) *Node { |
| if isRed(h.Right) && !isRed(h.Left) { |
| h = rotateLeft(h) |
| } |
| |
| if isRed(h.Left) && isRed(h.Left.Left) { |
| h = rotateRight(h) |
| } |
| |
| return h |
| } |
| |
| // DeleteMin deletes the minimum element in the tree and returns the |
| // deleted item or nil otherwise. |
| func (t *LLRB) DeleteMin() Item { |
| var deleted Item |
| t.root, deleted = deleteMin(t.root) |
| if t.root != nil { |
| t.root.Black = true |
| } |
| if deleted != nil { |
| t.count-- |
| } |
| return deleted |
| } |
| |
| // deleteMin code for LLRB 2-3 trees |
| func deleteMin(h *Node) (*Node, Item) { |
| if h == nil { |
| return nil, nil |
| } |
| if h.Left == nil { |
| return nil, h.Item |
| } |
| |
| if !isRed(h.Left) && !isRed(h.Left.Left) { |
| h = moveRedLeft(h) |
| } |
| |
| var deleted Item |
| h.Left, deleted = deleteMin(h.Left) |
| |
| return fixUp(h), deleted |
| } |
| |
| // DeleteMax deletes the maximum element in the tree and returns |
| // the deleted item or nil otherwise |
| func (t *LLRB) DeleteMax() Item { |
| var deleted Item |
| t.root, deleted = deleteMax(t.root) |
| if t.root != nil { |
| t.root.Black = true |
| } |
| if deleted != nil { |
| t.count-- |
| } |
| return deleted |
| } |
| |
| func deleteMax(h *Node) (*Node, Item) { |
| if h == nil { |
| return nil, nil |
| } |
| if isRed(h.Left) { |
| h = rotateRight(h) |
| } |
| if h.Right == nil { |
| return nil, h.Item |
| } |
| if !isRed(h.Right) && !isRed(h.Right.Left) { |
| h = moveRedRight(h) |
| } |
| var deleted Item |
| h.Right, deleted = deleteMax(h.Right) |
| |
| return fixUp(h), deleted |
| } |
| |
| // Delete deletes an item from the tree whose key equals key. |
| // The deleted item is return, otherwise nil is returned. |
| func (t *LLRB) Delete(key Item) Item { |
| var deleted Item |
| t.root, deleted = t.delete(t.root, key) |
| if t.root != nil { |
| t.root.Black = true |
| } |
| if deleted != nil { |
| t.count-- |
| } |
| return deleted |
| } |
| |
| func (t *LLRB) delete(h *Node, item Item) (*Node, Item) { |
| var deleted Item |
| if h == nil { |
| return nil, nil |
| } |
| if less(item, h.Item) { |
| if h.Left == nil { // item not present. Nothing to delete |
| return h, nil |
| } |
| if !isRed(h.Left) && !isRed(h.Left.Left) { |
| h = moveRedLeft(h) |
| } |
| h.Left, deleted = t.delete(h.Left, item) |
| } else { |
| if isRed(h.Left) { |
| h = rotateRight(h) |
| } |
| // If @item equals @h.Item and no right children at @h |
| if !less(h.Item, item) && h.Right == nil { |
| return nil, h.Item |
| } |
| // PETAR: Added 'h.Right != nil' below |
| if h.Right != nil && !isRed(h.Right) && !isRed(h.Right.Left) { |
| h = moveRedRight(h) |
| } |
| // If @item equals @h.Item, and (from above) 'h.Right != nil' |
| if !less(h.Item, item) { |
| var subDeleted Item |
| h.Right, subDeleted = deleteMin(h.Right) |
| if subDeleted == nil { |
| panic("logic") |
| } |
| deleted, h.Item = h.Item, subDeleted |
| } else { // Else, @item is bigger than @h.Item |
| h.Right, deleted = t.delete(h.Right, item) |
| } |
| } |
| |
| return fixUp(h), deleted |
| } |
| |
| // Internal node manipulation routines |
| |
| func newNode(item Item) *Node { return &Node{Item: item} } |
| |
| func isRed(h *Node) bool { |
| if h == nil { |
| return false |
| } |
| return !h.Black |
| } |
| |
| func rotateLeft(h *Node) *Node { |
| x := h.Right |
| if x.Black { |
| panic("rotating a black link") |
| } |
| h.Right = x.Left |
| x.Left = h |
| x.Black = h.Black |
| h.Black = false |
| return x |
| } |
| |
| func rotateRight(h *Node) *Node { |
| x := h.Left |
| if x.Black { |
| panic("rotating a black link") |
| } |
| h.Left = x.Right |
| x.Right = h |
| x.Black = h.Black |
| h.Black = false |
| return x |
| } |
| |
| // REQUIRE: Left and Right children must be present |
| func flip(h *Node) { |
| h.Black = !h.Black |
| h.Left.Black = !h.Left.Black |
| h.Right.Black = !h.Right.Black |
| } |
| |
| // REQUIRE: Left and Right children must be present |
| func moveRedLeft(h *Node) *Node { |
| flip(h) |
| if isRed(h.Right.Left) { |
| h.Right = rotateRight(h.Right) |
| h = rotateLeft(h) |
| flip(h) |
| } |
| return h |
| } |
| |
| // REQUIRE: Left and Right children must be present |
| func moveRedRight(h *Node) *Node { |
| flip(h) |
| if isRed(h.Left.Left) { |
| h = rotateRight(h) |
| flip(h) |
| } |
| return h |
| } |
| |
| func fixUp(h *Node) *Node { |
| if isRed(h.Right) { |
| h = rotateLeft(h) |
| } |
| |
| if isRed(h.Left) && isRed(h.Left.Left) { |
| h = rotateRight(h) |
| } |
| |
| if isRed(h.Left) && isRed(h.Right) { |
| flip(h) |
| } |
| |
| return h |
| } |