mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-13 18:43:34 +00:00
Updated vednor files
This commit is contained in:
23
vendor/github.com/petar/GoLLRB/.gitignore
generated
vendored
23
vendor/github.com/petar/GoLLRB/.gitignore
generated
vendored
@ -1,23 +0,0 @@
|
||||
syntax:glob
|
||||
*.[568ao]
|
||||
*.ao
|
||||
*.so
|
||||
*.pyc
|
||||
*.swp
|
||||
*.swo
|
||||
._*
|
||||
.nfs.*
|
||||
[568a].out
|
||||
*~
|
||||
*.orig
|
||||
*.pb.go
|
||||
core
|
||||
_obj
|
||||
_test
|
||||
src/pkg/Make.deps
|
||||
_testmain.go
|
||||
|
||||
syntax:regexp
|
||||
^pkg/
|
||||
^src/cmd/(.*)/6?\1$
|
||||
^.*/core.[0-9]*$
|
4
vendor/github.com/petar/GoLLRB/AUTHORS
generated
vendored
4
vendor/github.com/petar/GoLLRB/AUTHORS
generated
vendored
@ -1,4 +0,0 @@
|
||||
Petar Maymounkov <petar@5ttt.org>
|
||||
Vadim Vygonets <vadik@vygo.net>
|
||||
Ian Smith <iansmith@acm.org>
|
||||
Martin Bruse
|
27
vendor/github.com/petar/GoLLRB/LICENSE
generated
vendored
27
vendor/github.com/petar/GoLLRB/LICENSE
generated
vendored
@ -1,27 +0,0 @@
|
||||
Copyright (c) 2010, Petar Maymounkov
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
(*) Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
(*) Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
(*) Neither the name of Petar Maymounkov nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
66
vendor/github.com/petar/GoLLRB/README.md
generated
vendored
66
vendor/github.com/petar/GoLLRB/README.md
generated
vendored
@ -1,66 +0,0 @@
|
||||
# GoLLRB
|
||||
|
||||
GoLLRB is a Left-Leaning Red-Black (LLRB) implementation of 2-3 balanced binary
|
||||
search trees in Go Language.
|
||||
|
||||
## Overview
|
||||
|
||||
As of this writing and to the best of the author's knowledge,
|
||||
Go still does not have a balanced binary search tree (BBST) data structure.
|
||||
These data structures are quite useful in a variety of cases. A BBST maintains
|
||||
elements in sorted order under dynamic updates (inserts and deletes) and can
|
||||
support various order-specific queries. Furthermore, in practice one often
|
||||
implements other common data structures like Priority Queues, using BBST's.
|
||||
|
||||
2-3 trees (a type of BBST's), as well as the runtime-similar 2-3-4 trees, are
|
||||
the de facto standard BBST algoritms found in implementations of Python, Java,
|
||||
and other libraries. The LLRB method of implementing 2-3 trees is a recent
|
||||
improvement over the traditional implementation. The LLRB approach was
|
||||
discovered relatively recently (in 2008) by Robert Sedgewick of Princeton
|
||||
University.
|
||||
|
||||
GoLLRB is a Go implementation of LLRB 2-3 trees.
|
||||
|
||||
## Maturity
|
||||
|
||||
GoLLRB has been used in some pretty heavy-weight machine learning tasks over many gigabytes of data.
|
||||
I consider it to be in stable, perhaps even production, shape. There are no known bugs.
|
||||
|
||||
## Installation
|
||||
|
||||
With a healthy Go Language installed, simply run `go get github.com/petar/GoLLRB/llrb`
|
||||
|
||||
## Example
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/petar/GoLLRB/llrb"
|
||||
)
|
||||
|
||||
func lessInt(a, b interface{}) bool { return a.(int) < b.(int) }
|
||||
|
||||
func main() {
|
||||
tree := llrb.New(lessInt)
|
||||
tree.ReplaceOrInsert(1)
|
||||
tree.ReplaceOrInsert(2)
|
||||
tree.ReplaceOrInsert(3)
|
||||
tree.ReplaceOrInsert(4)
|
||||
tree.DeleteMin()
|
||||
tree.Delete(4)
|
||||
c := tree.IterAscend()
|
||||
for {
|
||||
u := <-c
|
||||
if u == nil {
|
||||
break
|
||||
}
|
||||
fmt.Printf("%d\n", int(u.(int)))
|
||||
}
|
||||
}
|
||||
|
||||
## About
|
||||
|
||||
GoLLRB was written by [Petar Maymounkov](http://pdos.csail.mit.edu/~petar/).
|
||||
|
||||
Follow me on [Twitter @maymounkov](http://www.twitter.com/maymounkov)!
|
4401
vendor/github.com/petar/GoLLRB/doc/Sedgewick-LLRB.pdf
generated
vendored
4401
vendor/github.com/petar/GoLLRB/doc/Sedgewick-LLRB.pdf
generated
vendored
File diff suppressed because one or more lines are too long
475
vendor/github.com/petar/GoLLRB/doc/Sedgewick-RedBlackBST.java
generated
vendored
475
vendor/github.com/petar/GoLLRB/doc/Sedgewick-RedBlackBST.java
generated
vendored
@ -1,475 +0,0 @@
|
||||
public class RedBlackBST<Key extends Comparable<Key>, Value>
|
||||
{
|
||||
private static final int BST = 0;
|
||||
private static final int TD234 = 1;
|
||||
private static final int BU23 = 2;
|
||||
private static final boolean RED = true;
|
||||
private static final boolean BLACK = false;
|
||||
|
||||
private Node root; // root of the BST
|
||||
private int k; // ordinal for drawing
|
||||
private final int species; // species kind of tree for insert
|
||||
private int heightBLACK; // black height of tree
|
||||
|
||||
RedBlackBST(int species)
|
||||
{ this.species = species; }
|
||||
|
||||
private class Node
|
||||
{
|
||||
Key key; // key
|
||||
Value value; // associated data
|
||||
Node left, right; // left and right subtrees
|
||||
boolean color; // color of parent link
|
||||
private int N; // number of nodes in tree rooted here
|
||||
private int height; // height of tree rooted here
|
||||
private double xc, yc; // for drawing
|
||||
|
||||
Node(Key key, Value value)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.color = RED;
|
||||
this.N = 1;
|
||||
this.height = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public int size()
|
||||
{ return size(root); }
|
||||
|
||||
private int size(Node x)
|
||||
{
|
||||
if (x == null) return 0;
|
||||
else return x.N;
|
||||
}
|
||||
|
||||
public int rootRank()
|
||||
{
|
||||
if (root == null) return 0;
|
||||
else return size(root.left);
|
||||
}
|
||||
|
||||
public int height()
|
||||
{ return height(root); }
|
||||
|
||||
public int heightB()
|
||||
{ return heightBLACK; }
|
||||
|
||||
private int height(Node x)
|
||||
{
|
||||
if (x == null) return 0;
|
||||
else return x.height;
|
||||
}
|
||||
|
||||
public boolean contains(Key key)
|
||||
{ return (get(key) != null); }
|
||||
|
||||
public Value get(Key key)
|
||||
{ return get(root, key); }
|
||||
|
||||
private Value get(Node x, Key key)
|
||||
{
|
||||
if (x == null) return null;
|
||||
if (eq (key, x.key)) return x.value;
|
||||
if (less(key, x.key)) return get(x.left, key);
|
||||
else return get(x.right, key);
|
||||
}
|
||||
|
||||
public Key min()
|
||||
{
|
||||
if (root == null) return null;
|
||||
else return min(root);
|
||||
}
|
||||
|
||||
private Key min(Node x)
|
||||
{
|
||||
if (x.left == null) return x.key;
|
||||
else return min(x.left);
|
||||
}
|
||||
|
||||
public Key max()
|
||||
{
|
||||
if (root == null) return null;
|
||||
else return max(root);
|
||||
}
|
||||
|
||||
private Key max(Node x)
|
||||
{
|
||||
if (x.right == null) return x.key;
|
||||
else return max(x.right);
|
||||
}
|
||||
|
||||
public void put(Key key, Value value)
|
||||
{
|
||||
root = insert(root, key, value);
|
||||
if (isRed(root)) heightBLACK++;
|
||||
root.color = BLACK;
|
||||
}
|
||||
|
||||
private Node insert(Node h, Key key, Value value)
|
||||
{
|
||||
if (h == null)
|
||||
return new Node(key, value);
|
||||
|
||||
if (species == TD234)
|
||||
if (isRed(h.left) && isRed(h.right))
|
||||
colorFlip(h);
|
||||
|
||||
if (eq(key, h.key))
|
||||
h.value = value;
|
||||
else if (less(key, h.key))
|
||||
h.left = insert(h.left, key, value);
|
||||
else
|
||||
h.right = insert(h.right, key, value);
|
||||
|
||||
if (species == BST) return setN(h);
|
||||
|
||||
if (isRed(h.right))
|
||||
h = rotateLeft(h);
|
||||
|
||||
if (isRed(h.left) && isRed(h.left.left))
|
||||
h = rotateRight(h);
|
||||
|
||||
if (species == BU23)
|
||||
if (isRed(h.left) && isRed(h.right))
|
||||
colorFlip(h);
|
||||
|
||||
return setN(h);
|
||||
}
|
||||
|
||||
public void deleteMin()
|
||||
{
|
||||
root = deleteMin(root);
|
||||
root.color = BLACK;
|
||||
}
|
||||
|
||||
private Node deleteMin(Node h)
|
||||
{
|
||||
if (h.left == null)
|
||||
return null;
|
||||
|
||||
if (!isRed(h.left) && !isRed(h.left.left))
|
||||
h = moveRedLeft(h);
|
||||
|
||||
h.left = deleteMin(h.left);
|
||||
|
||||
return fixUp(h);
|
||||
}
|
||||
|
||||
public void deleteMax()
|
||||
{
|
||||
root = deleteMax(root);
|
||||
root.color = BLACK;
|
||||
}
|
||||
|
||||
private Node deleteMax(Node h)
|
||||
{
|
||||
// if (h.right == null)
|
||||
// {
|
||||
// if (h.left != null)
|
||||
// h.left.color = BLACK;
|
||||
// return h.left;
|
||||
// }
|
||||
|
||||
if (isRed(h.left))
|
||||
h = rotateRight(h);
|
||||
|
||||
if (h.right == null)
|
||||
return null;
|
||||
|
||||
if (!isRed(h.right) && !isRed(h.right.left))
|
||||
h = moveRedRight(h);
|
||||
|
||||
h.right = deleteMax(h.right);
|
||||
|
||||
return fixUp(h);
|
||||
}
|
||||
|
||||
public void delete(Key key)
|
||||
{
|
||||
root = delete(root, key);
|
||||
root.color = BLACK;
|
||||
}
|
||||
|
||||
private Node delete(Node h, Key key)
|
||||
{
|
||||
if (less(key, h.key))
|
||||
{
|
||||
if (!isRed(h.left) && !isRed(h.left.left))
|
||||
h = moveRedLeft(h);
|
||||
h.left = delete(h.left, key);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isRed(h.left))
|
||||
h = rotateRight(h);
|
||||
if (eq(key, h.key) && (h.right == null))
|
||||
return null;
|
||||
if (!isRed(h.right) && !isRed(h.right.left))
|
||||
h = moveRedRight(h);
|
||||
if (eq(key, h.key))
|
||||
{
|
||||
h.value = get(h.right, min(h.right));
|
||||
h.key = min(h.right);
|
||||
h.right = deleteMin(h.right);
|
||||
}
|
||||
else h.right = delete(h.right, key);
|
||||
}
|
||||
|
||||
return fixUp(h);
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
private boolean less(Key a, Key b) { return a.compareTo(b) < 0; }
|
||||
private boolean eq (Key a, Key b) { return a.compareTo(b) == 0; }
|
||||
|
||||
private boolean isRed(Node x)
|
||||
{
|
||||
if (x == null) return false;
|
||||
return (x.color == RED);
|
||||
}
|
||||
|
||||
private void colorFlip(Node h)
|
||||
{
|
||||
h.color = !h.color;
|
||||
h.left.color = !h.left.color;
|
||||
h.right.color = !h.right.color;
|
||||
}
|
||||
|
||||
private Node rotateLeft(Node h)
|
||||
{ // Make a right-leaning 3-node lean to the left.
|
||||
Node x = h.right;
|
||||
h.right = x.left;
|
||||
x.left = setN(h);
|
||||
x.color = x.left.color;
|
||||
x.left.color = RED;
|
||||
return setN(x);
|
||||
}
|
||||
|
||||
private Node rotateRight(Node h)
|
||||
{ // Make a left-leaning 3-node lean to the right.
|
||||
Node x = h.left;
|
||||
h.left = x.right;
|
||||
x.right = setN(h);
|
||||
x.color = x.right.color;
|
||||
x.right.color = RED;
|
||||
return setN(x);
|
||||
}
|
||||
|
||||
private Node moveRedLeft(Node h)
|
||||
{ // Assuming that h is red and both h.left and h.left.left
|
||||
// are black, make h.left or one of its children red.
|
||||
colorFlip(h);
|
||||
if (isRed(h.right.left))
|
||||
{
|
||||
h.right = rotateRight(h.right);
|
||||
h = rotateLeft(h);
|
||||
colorFlip(h);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
private Node moveRedRight(Node h)
|
||||
{ // Assuming that h is red and both h.right and h.right.left
|
||||
// are black, make h.right or one of its children red.
|
||||
colorFlip(h);
|
||||
if (isRed(h.left.left))
|
||||
{
|
||||
h = rotateRight(h);
|
||||
colorFlip(h);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
private Node fixUp(Node h)
|
||||
{
|
||||
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))
|
||||
colorFlip(h);
|
||||
|
||||
return setN(h);
|
||||
}
|
||||
|
||||
private Node setN(Node h)
|
||||
{
|
||||
h.N = size(h.left) + size(h.right) + 1;
|
||||
if (height(h.left) > height(h.right)) h.height = height(h.left) + 1;
|
||||
else h.height = height(h.right) + 1;
|
||||
return h;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
if (root == null) return "";
|
||||
else return heightB() + " " + toString(root);
|
||||
}
|
||||
|
||||
public String toString(Node x)
|
||||
{
|
||||
String s = "(";
|
||||
if (x.left == null) s += "("; else s += toString(x.left);
|
||||
if (isRed(x)) s += "*";
|
||||
if (x.right == null) s += ")"; else s += toString(x.right);
|
||||
return s + ")";
|
||||
}
|
||||
|
||||
// Methods for tree drawing
|
||||
|
||||
public void draw(double y, double lineWidth, double nodeSize)
|
||||
{
|
||||
k = 0;
|
||||
setcoords(root, y);
|
||||
StdDraw.setPenColor(StdDraw.BLACK);
|
||||
StdDraw.setPenRadius(lineWidth);
|
||||
drawlines(root);
|
||||
StdDraw.setPenColor(StdDraw.WHITE);
|
||||
drawnodes(root, nodeSize);
|
||||
}
|
||||
|
||||
public void setcoords(Node x, double d)
|
||||
{
|
||||
if (x == null) return;
|
||||
setcoords(x.left, d-.04);
|
||||
x.xc = (0.5 + k++)/size(); x.yc = d - .04;
|
||||
setcoords(x.right, d-.04);
|
||||
}
|
||||
|
||||
public void drawlines(Node x)
|
||||
{
|
||||
if (x == null) return;
|
||||
drawlines(x.left);
|
||||
if (x.left != null)
|
||||
{
|
||||
if (x.left.color == RED) StdDraw.setPenColor(StdDraw.RED);
|
||||
else StdDraw.setPenColor(StdDraw.BLACK);
|
||||
StdDraw.line(x.xc, x.yc, x.left.xc, x.left.yc);
|
||||
}
|
||||
if (x.right != null)
|
||||
{
|
||||
if (x.right.color == RED) StdDraw.setPenColor(StdDraw.RED);
|
||||
else StdDraw.setPenColor(StdDraw.BLACK);
|
||||
StdDraw.line(x.xc, x.yc, x.right.xc, x.right.yc);
|
||||
}
|
||||
drawlines(x.right);
|
||||
}
|
||||
|
||||
public void drawnodes(Node x, double nodeSize)
|
||||
{
|
||||
if (x == null) return;
|
||||
drawnodes(x.left, nodeSize);
|
||||
StdDraw.filledCircle(x.xc, x.yc, nodeSize);
|
||||
drawnodes(x.right, nodeSize);
|
||||
}
|
||||
|
||||
public void mark(Key key)
|
||||
{
|
||||
StdDraw.setPenColor(StdDraw.BLACK);
|
||||
marknodes(key, root);
|
||||
}
|
||||
|
||||
public void marknodes(Key key, Node x)
|
||||
{
|
||||
if (x == null) return;
|
||||
marknodes(key, x.left);
|
||||
if (eq(key, x.key))
|
||||
StdDraw.filledCircle(x.xc, x.yc, .004);
|
||||
marknodes(key, x.right);
|
||||
}
|
||||
|
||||
public int ipl()
|
||||
{ return ipl(root); }
|
||||
|
||||
public int ipl(Node x)
|
||||
{
|
||||
if (x == null) return 0;
|
||||
return size(x) - 1 + ipl(x.left) + ipl(x.right);
|
||||
}
|
||||
|
||||
public int sizeRed()
|
||||
{ return sizeRed(root); }
|
||||
|
||||
public int sizeRed(Node x)
|
||||
{
|
||||
if (x == null) return 0;
|
||||
if (isRed(x)) return 1 + sizeRed(x.left) + sizeRed(x.right);
|
||||
else return sizeRed(x.left) + sizeRed(x.right);
|
||||
}
|
||||
|
||||
// Integrity checks
|
||||
|
||||
public boolean check()
|
||||
{ // Is this tree a red-black tree?
|
||||
return isBST() && is234() && isBalanced();
|
||||
}
|
||||
|
||||
private boolean isBST()
|
||||
{ // Is this tree a BST?
|
||||
return isBST(root, min(), max());
|
||||
}
|
||||
|
||||
private boolean isBST(Node x, Key min, Key max)
|
||||
{ // Are all the values in the BST rooted at x between min and max,
|
||||
// and does the same property hold for both subtrees?
|
||||
if (x == null) return true;
|
||||
if (less(x.key, min) || less(max, x.key)) return false;
|
||||
return isBST(x.left, min, x.key) && isBST(x.right, x.key, max);
|
||||
}
|
||||
|
||||
private boolean is234() { return is234(root); }
|
||||
private boolean is234(Node x)
|
||||
{ // Does the tree have no red right links, and at most two (left)
|
||||
// red links in a row on any path?
|
||||
if (x == null) return true;
|
||||
if (isRed(x.right)) return false;
|
||||
if (isRed(x))
|
||||
if (isRed(x.left))
|
||||
if (isRed(x.left.left)) return false;
|
||||
return is234(x.left) && is234(x.right);
|
||||
}
|
||||
|
||||
private boolean isBalanced()
|
||||
{ // Do all paths from root to leaf have same number of black edges?
|
||||
int black = 0; // number of black links on path from root to min
|
||||
Node x = root;
|
||||
while (x != null)
|
||||
{
|
||||
if (!isRed(x)) black++;
|
||||
x = x.left;
|
||||
}
|
||||
return isBalanced(root, black);
|
||||
}
|
||||
|
||||
private boolean isBalanced(Node x, int black)
|
||||
{ // Does every path from the root to a leaf have the given number
|
||||
// of black links?
|
||||
if (x == null && black == 0) return true;
|
||||
else if (x == null && black != 0) return false;
|
||||
if (!isRed(x)) black--;
|
||||
return isBalanced(x.left, black) && isBalanced(x.right, black);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
StdDraw.setPenRadius(.0025);
|
||||
int species = Integer.parseInt(args[0]);
|
||||
RedBlackBST<Integer, Integer> st;
|
||||
st = new RedBlackBST<Integer, Integer>(species);
|
||||
int[] a = { 3, 1, 4, 2, 5, 9, 6, 8, 7 };
|
||||
for (int i = 0; i < a.length; i++)
|
||||
st.put(a[i], i);
|
||||
StdOut.println(st);
|
||||
StdDraw.clear(StdDraw.LIGHT_GRAY);
|
||||
st.draw(.95, .0025, .008);
|
||||
StdOut.println(st.min() + " " + st.max() + " " + st.check());
|
||||
StdOut.println(st.ipl());
|
||||
StdOut.println(st.heightB());
|
||||
}
|
||||
|
||||
}
|
BIN
vendor/github.com/petar/GoLLRB/doc/Sedgewick-Talk-Penn2008.pdf
generated
vendored
BIN
vendor/github.com/petar/GoLLRB/doc/Sedgewick-Talk-Penn2008.pdf
generated
vendored
Binary file not shown.
26
vendor/github.com/petar/GoLLRB/example/ex1.go
generated
vendored
26
vendor/github.com/petar/GoLLRB/example/ex1.go
generated
vendored
@ -1,26 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/petar/GoLLRB/llrb"
|
||||
)
|
||||
|
||||
func lessInt(a, b interface{}) bool { return a.(int) < b.(int) }
|
||||
|
||||
func main() {
|
||||
tree := llrb.New(lessInt)
|
||||
tree.ReplaceOrInsert(1)
|
||||
tree.ReplaceOrInsert(2)
|
||||
tree.ReplaceOrInsert(3)
|
||||
tree.ReplaceOrInsert(4)
|
||||
tree.DeleteMin()
|
||||
tree.Delete(4)
|
||||
c := tree.IterAscend()
|
||||
for {
|
||||
u := <-c
|
||||
if u == nil {
|
||||
break
|
||||
}
|
||||
fmt.Printf("%d\n", int(u.(int)))
|
||||
}
|
||||
}
|
39
vendor/github.com/petar/GoLLRB/llrb/avgvar.go
generated
vendored
39
vendor/github.com/petar/GoLLRB/llrb/avgvar.go
generated
vendored
@ -1,39 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package llrb
|
||||
|
||||
import "math"
|
||||
|
||||
// avgVar maintains the average and variance of a stream of numbers
|
||||
// in a space-efficient manner.
|
||||
type avgVar struct {
|
||||
count int64
|
||||
sum, sumsq float64
|
||||
}
|
||||
|
||||
func (av *avgVar) Init() {
|
||||
av.count = 0
|
||||
av.sum = 0.0
|
||||
av.sumsq = 0.0
|
||||
}
|
||||
|
||||
func (av *avgVar) Add(sample float64) {
|
||||
av.count++
|
||||
av.sum += sample
|
||||
av.sumsq += sample * sample
|
||||
}
|
||||
|
||||
func (av *avgVar) GetCount() int64 { return av.count }
|
||||
|
||||
func (av *avgVar) GetAvg() float64 { return av.sum / float64(av.count) }
|
||||
|
||||
func (av *avgVar) GetTotal() float64 { return av.sum }
|
||||
|
||||
func (av *avgVar) GetVar() float64 {
|
||||
a := av.GetAvg()
|
||||
return av.sumsq/float64(av.count) - a*a
|
||||
}
|
||||
|
||||
func (av *avgVar) GetStdDev() float64 { return math.Sqrt(av.GetVar()) }
|
93
vendor/github.com/petar/GoLLRB/llrb/iterator.go
generated
vendored
93
vendor/github.com/petar/GoLLRB/llrb/iterator.go
generated
vendored
@ -1,93 +0,0 @@
|
||||
package llrb
|
||||
|
||||
type ItemIterator func(i Item) bool
|
||||
|
||||
//func (t *Tree) Ascend(iterator ItemIterator) {
|
||||
// t.AscendGreaterOrEqual(Inf(-1), iterator)
|
||||
//}
|
||||
|
||||
func (t *LLRB) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator) {
|
||||
t.ascendRange(t.root, greaterOrEqual, lessThan, iterator)
|
||||
}
|
||||
|
||||
func (t *LLRB) ascendRange(h *Node, inf, sup Item, iterator ItemIterator) bool {
|
||||
if h == nil {
|
||||
return true
|
||||
}
|
||||
if !less(h.Item, sup) {
|
||||
return t.ascendRange(h.Left, inf, sup, iterator)
|
||||
}
|
||||
if less(h.Item, inf) {
|
||||
return t.ascendRange(h.Right, inf, sup, iterator)
|
||||
}
|
||||
|
||||
if !t.ascendRange(h.Left, inf, sup, iterator) {
|
||||
return false
|
||||
}
|
||||
if !iterator(h.Item) {
|
||||
return false
|
||||
}
|
||||
return t.ascendRange(h.Right, inf, sup, iterator)
|
||||
}
|
||||
|
||||
// AscendGreaterOrEqual will call iterator once for each element greater or equal to
|
||||
// pivot in ascending order. It will stop whenever the iterator returns false.
|
||||
func (t *LLRB) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) {
|
||||
t.ascendGreaterOrEqual(t.root, pivot, iterator)
|
||||
}
|
||||
|
||||
func (t *LLRB) ascendGreaterOrEqual(h *Node, pivot Item, iterator ItemIterator) bool {
|
||||
if h == nil {
|
||||
return true
|
||||
}
|
||||
if !less(h.Item, pivot) {
|
||||
if !t.ascendGreaterOrEqual(h.Left, pivot, iterator) {
|
||||
return false
|
||||
}
|
||||
if !iterator(h.Item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return t.ascendGreaterOrEqual(h.Right, pivot, iterator)
|
||||
}
|
||||
|
||||
func (t *LLRB) AscendLessThan(pivot Item, iterator ItemIterator) {
|
||||
t.ascendLessThan(t.root, pivot, iterator)
|
||||
}
|
||||
|
||||
func (t *LLRB) ascendLessThan(h *Node, pivot Item, iterator ItemIterator) bool {
|
||||
if h == nil {
|
||||
return true
|
||||
}
|
||||
if !t.ascendLessThan(h.Left, pivot, iterator) {
|
||||
return false
|
||||
}
|
||||
if !iterator(h.Item) {
|
||||
return false
|
||||
}
|
||||
if less(h.Item, pivot) {
|
||||
return t.ascendLessThan(h.Left, pivot, iterator)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// DescendLessOrEqual will call iterator once for each element less than the
|
||||
// pivot in descending order. It will stop whenever the iterator returns false.
|
||||
func (t *LLRB) DescendLessOrEqual(pivot Item, iterator ItemIterator) {
|
||||
t.descendLessOrEqual(t.root, pivot, iterator)
|
||||
}
|
||||
|
||||
func (t *LLRB) descendLessOrEqual(h *Node, pivot Item, iterator ItemIterator) bool {
|
||||
if h == nil {
|
||||
return true
|
||||
}
|
||||
if less(h.Item, pivot) || !less(pivot, h.Item) {
|
||||
if !t.descendLessOrEqual(h.Right, pivot, iterator) {
|
||||
return false
|
||||
}
|
||||
if !iterator(h.Item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return t.descendLessOrEqual(h.Left, pivot, iterator)
|
||||
}
|
76
vendor/github.com/petar/GoLLRB/llrb/iterator_test.go
generated
vendored
76
vendor/github.com/petar/GoLLRB/llrb/iterator_test.go
generated
vendored
@ -1,76 +0,0 @@
|
||||
package llrb
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAscendGreaterOrEqual(t *testing.T) {
|
||||
tree := New()
|
||||
tree.InsertNoReplace(Int(4))
|
||||
tree.InsertNoReplace(Int(6))
|
||||
tree.InsertNoReplace(Int(1))
|
||||
tree.InsertNoReplace(Int(3))
|
||||
var ary []Item
|
||||
tree.AscendGreaterOrEqual(Int(-1), func(i Item) bool {
|
||||
ary = append(ary, i)
|
||||
return true
|
||||
})
|
||||
expected := []Item{Int(1), Int(3), Int(4), Int(6)}
|
||||
if !reflect.DeepEqual(ary, expected) {
|
||||
t.Errorf("expected %v but got %v", expected, ary)
|
||||
}
|
||||
ary = nil
|
||||
tree.AscendGreaterOrEqual(Int(3), func(i Item) bool {
|
||||
ary = append(ary, i)
|
||||
return true
|
||||
})
|
||||
expected = []Item{Int(3), Int(4), Int(6)}
|
||||
if !reflect.DeepEqual(ary, expected) {
|
||||
t.Errorf("expected %v but got %v", expected, ary)
|
||||
}
|
||||
ary = nil
|
||||
tree.AscendGreaterOrEqual(Int(2), func(i Item) bool {
|
||||
ary = append(ary, i)
|
||||
return true
|
||||
})
|
||||
expected = []Item{Int(3), Int(4), Int(6)}
|
||||
if !reflect.DeepEqual(ary, expected) {
|
||||
t.Errorf("expected %v but got %v", expected, ary)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDescendLessOrEqual(t *testing.T) {
|
||||
tree := New()
|
||||
tree.InsertNoReplace(Int(4))
|
||||
tree.InsertNoReplace(Int(6))
|
||||
tree.InsertNoReplace(Int(1))
|
||||
tree.InsertNoReplace(Int(3))
|
||||
var ary []Item
|
||||
tree.DescendLessOrEqual(Int(10), func(i Item) bool {
|
||||
ary = append(ary, i)
|
||||
return true
|
||||
})
|
||||
expected := []Item{Int(6), Int(4), Int(3), Int(1)}
|
||||
if !reflect.DeepEqual(ary, expected) {
|
||||
t.Errorf("expected %v but got %v", expected, ary)
|
||||
}
|
||||
ary = nil
|
||||
tree.DescendLessOrEqual(Int(4), func(i Item) bool {
|
||||
ary = append(ary, i)
|
||||
return true
|
||||
})
|
||||
expected = []Item{Int(4), Int(3), Int(1)}
|
||||
if !reflect.DeepEqual(ary, expected) {
|
||||
t.Errorf("expected %v but got %v", expected, ary)
|
||||
}
|
||||
ary = nil
|
||||
tree.DescendLessOrEqual(Int(5), func(i Item) bool {
|
||||
ary = append(ary, i)
|
||||
return true
|
||||
})
|
||||
expected = []Item{Int(4), Int(3), Int(1)}
|
||||
if !reflect.DeepEqual(ary, expected) {
|
||||
t.Errorf("expected %v but got %v", expected, ary)
|
||||
}
|
||||
}
|
46
vendor/github.com/petar/GoLLRB/llrb/llrb-stats.go
generated
vendored
46
vendor/github.com/petar/GoLLRB/llrb/llrb-stats.go
generated
vendored
@ -1,46 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package llrb
|
||||
|
||||
// GetHeight() returns an item in the tree with key @key, and it's height in the tree
|
||||
func (t *LLRB) GetHeight(key Item) (result Item, depth int) {
|
||||
return t.getHeight(t.root, key)
|
||||
}
|
||||
|
||||
func (t *LLRB) getHeight(h *Node, item Item) (Item, int) {
|
||||
if h == nil {
|
||||
return nil, 0
|
||||
}
|
||||
if less(item, h.Item) {
|
||||
result, depth := t.getHeight(h.Left, item)
|
||||
return result, depth + 1
|
||||
}
|
||||
if less(h.Item, item) {
|
||||
result, depth := t.getHeight(h.Right, item)
|
||||
return result, depth + 1
|
||||
}
|
||||
return h.Item, 0
|
||||
}
|
||||
|
||||
// HeightStats() returns the average and standard deviation of the height
|
||||
// of elements in the tree
|
||||
func (t *LLRB) HeightStats() (avg, stddev float64) {
|
||||
av := &avgVar{}
|
||||
heightStats(t.root, 0, av)
|
||||
return av.GetAvg(), av.GetStdDev()
|
||||
}
|
||||
|
||||
func heightStats(h *Node, d int, av *avgVar) {
|
||||
if h == nil {
|
||||
return
|
||||
}
|
||||
av.Add(float64(d))
|
||||
if h.Left != nil {
|
||||
heightStats(h.Left, d+1, av)
|
||||
}
|
||||
if h.Right != nil {
|
||||
heightStats(h.Right, d+1, av)
|
||||
}
|
||||
}
|
456
vendor/github.com/petar/GoLLRB/llrb/llrb.go
generated
vendored
456
vendor/github.com/petar/GoLLRB/llrb/llrb.go
generated
vendored
@ -1,456 +0,0 @@
|
||||
// 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
|
||||
}
|
239
vendor/github.com/petar/GoLLRB/llrb/llrb_test.go
generated
vendored
239
vendor/github.com/petar/GoLLRB/llrb/llrb_test.go
generated
vendored
@ -1,239 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package llrb
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCases(t *testing.T) {
|
||||
tree := New()
|
||||
tree.ReplaceOrInsert(Int(1))
|
||||
tree.ReplaceOrInsert(Int(1))
|
||||
if tree.Len() != 1 {
|
||||
t.Errorf("expecting len 1")
|
||||
}
|
||||
if !tree.Has(Int(1)) {
|
||||
t.Errorf("expecting to find key=1")
|
||||
}
|
||||
|
||||
tree.Delete(Int(1))
|
||||
if tree.Len() != 0 {
|
||||
t.Errorf("expecting len 0")
|
||||
}
|
||||
if tree.Has(Int(1)) {
|
||||
t.Errorf("not expecting to find key=1")
|
||||
}
|
||||
|
||||
tree.Delete(Int(1))
|
||||
if tree.Len() != 0 {
|
||||
t.Errorf("expecting len 0")
|
||||
}
|
||||
if tree.Has(Int(1)) {
|
||||
t.Errorf("not expecting to find key=1")
|
||||
}
|
||||
}
|
||||
|
||||
func TestReverseInsertOrder(t *testing.T) {
|
||||
tree := New()
|
||||
n := 100
|
||||
for i := 0; i < n; i++ {
|
||||
tree.ReplaceOrInsert(Int(n - i))
|
||||
}
|
||||
i := 0
|
||||
tree.AscendGreaterOrEqual(Int(0), func(item Item) bool {
|
||||
i++
|
||||
if item.(Int) != Int(i) {
|
||||
t.Errorf("bad order: got %d, expect %d", item.(Int), i)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func TestRange(t *testing.T) {
|
||||
tree := New()
|
||||
order := []String{
|
||||
"ab", "aba", "abc", "a", "aa", "aaa", "b", "a-", "a!",
|
||||
}
|
||||
for _, i := range order {
|
||||
tree.ReplaceOrInsert(i)
|
||||
}
|
||||
k := 0
|
||||
tree.AscendRange(String("ab"), String("ac"), func(item Item) bool {
|
||||
if k > 3 {
|
||||
t.Fatalf("returned more items than expected")
|
||||
}
|
||||
i1 := order[k]
|
||||
i2 := item.(String)
|
||||
if i1 != i2 {
|
||||
t.Errorf("expecting %s, got %s", i1, i2)
|
||||
}
|
||||
k++
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func TestRandomInsertOrder(t *testing.T) {
|
||||
tree := New()
|
||||
n := 1000
|
||||
perm := rand.Perm(n)
|
||||
for i := 0; i < n; i++ {
|
||||
tree.ReplaceOrInsert(Int(perm[i]))
|
||||
}
|
||||
j := 0
|
||||
tree.AscendGreaterOrEqual(Int(0), func(item Item) bool {
|
||||
if item.(Int) != Int(j) {
|
||||
t.Fatalf("bad order")
|
||||
}
|
||||
j++
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func TestRandomReplace(t *testing.T) {
|
||||
tree := New()
|
||||
n := 100
|
||||
perm := rand.Perm(n)
|
||||
for i := 0; i < n; i++ {
|
||||
tree.ReplaceOrInsert(Int(perm[i]))
|
||||
}
|
||||
perm = rand.Perm(n)
|
||||
for i := 0; i < n; i++ {
|
||||
if replaced := tree.ReplaceOrInsert(Int(perm[i])); replaced == nil || replaced.(Int) != Int(perm[i]) {
|
||||
t.Errorf("error replacing")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandomInsertSequentialDelete(t *testing.T) {
|
||||
tree := New()
|
||||
n := 1000
|
||||
perm := rand.Perm(n)
|
||||
for i := 0; i < n; i++ {
|
||||
tree.ReplaceOrInsert(Int(perm[i]))
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
tree.Delete(Int(i))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandomInsertDeleteNonExistent(t *testing.T) {
|
||||
tree := New()
|
||||
n := 100
|
||||
perm := rand.Perm(n)
|
||||
for i := 0; i < n; i++ {
|
||||
tree.ReplaceOrInsert(Int(perm[i]))
|
||||
}
|
||||
if tree.Delete(Int(200)) != nil {
|
||||
t.Errorf("deleted non-existent item")
|
||||
}
|
||||
if tree.Delete(Int(-2)) != nil {
|
||||
t.Errorf("deleted non-existent item")
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
if u := tree.Delete(Int(i)); u == nil || u.(Int) != Int(i) {
|
||||
t.Errorf("delete failed")
|
||||
}
|
||||
}
|
||||
if tree.Delete(Int(200)) != nil {
|
||||
t.Errorf("deleted non-existent item")
|
||||
}
|
||||
if tree.Delete(Int(-2)) != nil {
|
||||
t.Errorf("deleted non-existent item")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandomInsertPartialDeleteOrder(t *testing.T) {
|
||||
tree := New()
|
||||
n := 100
|
||||
perm := rand.Perm(n)
|
||||
for i := 0; i < n; i++ {
|
||||
tree.ReplaceOrInsert(Int(perm[i]))
|
||||
}
|
||||
for i := 1; i < n-1; i++ {
|
||||
tree.Delete(Int(i))
|
||||
}
|
||||
j := 0
|
||||
tree.AscendGreaterOrEqual(Int(0), func(item Item) bool {
|
||||
switch j {
|
||||
case 0:
|
||||
if item.(Int) != Int(0) {
|
||||
t.Errorf("expecting 0")
|
||||
}
|
||||
case 1:
|
||||
if item.(Int) != Int(n-1) {
|
||||
t.Errorf("expecting %d", n-1)
|
||||
}
|
||||
}
|
||||
j++
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func TestRandomInsertStats(t *testing.T) {
|
||||
tree := New()
|
||||
n := 100000
|
||||
perm := rand.Perm(n)
|
||||
for i := 0; i < n; i++ {
|
||||
tree.ReplaceOrInsert(Int(perm[i]))
|
||||
}
|
||||
avg, _ := tree.HeightStats()
|
||||
expAvg := math.Log2(float64(n)) - 1.5
|
||||
if math.Abs(avg-expAvg) >= 2.0 {
|
||||
t.Errorf("too much deviation from expected average height")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkInsert(b *testing.B) {
|
||||
tree := New()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tree.ReplaceOrInsert(Int(b.N - i))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDelete(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tree := New()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tree.ReplaceOrInsert(Int(b.N - i))
|
||||
}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tree.Delete(Int(i))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkDeleteMin(b *testing.B) {
|
||||
b.StopTimer()
|
||||
tree := New()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tree.ReplaceOrInsert(Int(b.N - i))
|
||||
}
|
||||
b.StartTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
tree.DeleteMin()
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertNoReplace(t *testing.T) {
|
||||
tree := New()
|
||||
n := 1000
|
||||
for q := 0; q < 2; q++ {
|
||||
perm := rand.Perm(n)
|
||||
for i := 0; i < n; i++ {
|
||||
tree.InsertNoReplace(Int(perm[i]))
|
||||
}
|
||||
}
|
||||
j := 0
|
||||
tree.AscendGreaterOrEqual(Int(0), func(item Item) bool {
|
||||
if item.(Int) != Int(j/2) {
|
||||
t.Fatalf("bad order")
|
||||
}
|
||||
j++
|
||||
return true
|
||||
})
|
||||
}
|
17
vendor/github.com/petar/GoLLRB/llrb/util.go
generated
vendored
17
vendor/github.com/petar/GoLLRB/llrb/util.go
generated
vendored
@ -1,17 +0,0 @@
|
||||
// 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.
|
||||
|
||||
package llrb
|
||||
|
||||
type Int int
|
||||
|
||||
func (x Int) Less(than Item) bool {
|
||||
return x < than.(Int)
|
||||
}
|
||||
|
||||
type String string
|
||||
|
||||
func (x String) Less(than Item) bool {
|
||||
return x < than.(String)
|
||||
}
|
Reference in New Issue
Block a user