* Dropped unused codekit config * Integrated dynamic and static bindata for public * Ignore public bindata * Add a general generate make task * Integrated flexible public assets into web command * Updated vendoring, added all missiong govendor deps * Made the linter happy with the bindata and dynamic code * Moved public bindata definition to modules directory * Ignoring the new bindata path now * Updated to the new public modules import path * Updated public bindata command and drop the new prefix
		
			
				
	
	
		
			457 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			457 lines
		
	
	
		
			8.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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
 | |
| }
 |