From 6f6a64ed0800db5d2a117b54f0385e8090a3c2ee Mon Sep 17 00:00:00 2001
From: huangsimin <huangsimin@youmi.net>
Date: Tue, 26 Mar 2019 19:17:57 +0800
Subject: [PATCH] priority_queue TODO

---
 avl/avl_test.go            |  16 +-
 priority_queue/vbt.go      | 271 +++++++++------
 priority_queue/vbt_test.go | 678 +++++++++++++++++++++++++++++++++++++
 3 files changed, 845 insertions(+), 120 deletions(-)
 create mode 100644 priority_queue/vbt_test.go

diff --git a/avl/avl_test.go b/avl/avl_test.go
index 13842ea..38eb06a 100644
--- a/avl/avl_test.go
+++ b/avl/avl_test.go
@@ -247,17 +247,11 @@ func TestPutStable(t *testing.T) {
 	// log.SetOutput(f)
 	// 0-1 3 | 2-3 7-8 | 4-7 12-16 | 8-15 20-32 | 16-31 33-58 l := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 18, 19, 20, 21, 22, 30, 41, 41, 41}
 
-	// for i := 0; i < 100000; i++ {
-	// 	var l []int
-	// 	for len(l) < 1000 {
-	// 		l = append(l, randomdata.Number(0, 100))
-	// 	}
-
-	// 	tree := New(compare.Int)
-	// 	for _, v := range l {
-	// 		tree.Put(v)
-	// 	}
-	// }
+	tree := New(compare.Int)
+	for i := 0; i < 10; i++ {
+		tree.Put(randomdata.Number(0, 100))
+	}
+	t.Error(tree.debugString())
 
 	// t.Error(tree.debugString(), tree.TraversalBreadth(), "\n", "-----------")
 }
diff --git a/priority_queue/vbt.go b/priority_queue/vbt.go
index 87c4c7b..9f7c61b 100644
--- a/priority_queue/vbt.go
+++ b/priority_queue/vbt.go
@@ -1,6 +1,8 @@
 package pqueue
 
 import (
+	"log"
+
 	"474420502.top/eson/structure/compare"
 	"github.com/davecgh/go-spew/spew"
 )
@@ -203,17 +205,11 @@ func (tree *vbTree) removeNode(n *tNode) {
 	}
 
 	cparent := cur.parent
+	replaceNodeMayRoot(n, cur)
 	// 修改为interface 交换
-	n.value, cur.value = cur.value, n.value
+	// n.value, cur.value = cur.value, n.value
 
-	// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
-	if cparent == n {
-		tree.fixSizeWithRemove(n)
-	} else {
-		tree.fixSizeWithRemove(cparent)
-	}
-
-	// return cur
+	tree.fixSizeWithRemove(cparent)
 	return
 }
 
@@ -624,44 +620,42 @@ func (tree *vbTree) lrrotate3(cur *tNode) {
 	cur.children[l].size = 1
 }
 
-func (tree *vbTree) lrrotate(cur *tNode) {
+func (tree *vbTree) lrrotate(cur *tNode) *tNode {
 
 	const l = 1
 	const r = 0
 
-	movparent := cur.children[l]
-	mov := movparent.children[r]
+	// 1 right 0 left
+	ln := cur.children[l]
+	lrn := ln.children[r] // 待转换的节点
+	lrln := lrn.children[l]
+	lrrn := lrn.children[r]
 
-	mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
+	ln.children[r] = lrln
+	ln.children[r].parent = ln
 
-	if mov.children[l] != nil {
-		movparent.children[r] = mov.children[l]
-		movparent.children[r].parent = movparent
-		//movparent.children[r].child = l
-	} else {
-		movparent.children[r] = nil
+	if cur.parent != nil {
+		if cur.parent.children[l] == cur {
+			cur.parent.children[l] = lrn
+		} else {
+			cur.parent.children[r] = lrn
+		}
 	}
 
-	if mov.children[r] != nil {
-		mov.children[l] = mov.children[r]
-		//mov.children[l].child = l
-	} else {
-		mov.children[l] = nil
-	}
+	lrn.children[l] = cur.children[l]
+	lrn.children[l].parent = lrn
 
-	if cur.children[r] != nil {
-		mov.children[r] = cur.children[r]
-		mov.children[r].parent = mov
-	} else {
-		mov.children[r] = nil
-	}
+	lrn.children[l] = cur
+	lrn.children[l].parent = lrn
 
-	cur.children[r] = mov
-	mov.parent = cur
+	cur.children[l] = lrrn
+	cur.children[l].parent = cur
 
-	movparent.size = getChildrenSumSize(movparent) + 1
-	mov.size = getChildrenSumSize(mov) + 1
+	ln.size = getChildrenSumSize(ln) + 1
 	cur.size = getChildrenSumSize(cur) + 1
+	lrn.size = getChildrenSumSize(lrn) + 1
+
+	return lrn
 }
 
 func (tree *vbTree) rlrotate3(cur *tNode) {
@@ -687,42 +681,42 @@ func (tree *vbTree) rlrotate3(cur *tNode) {
 	cur.children[l].size = 1
 }
 
-func (tree *vbTree) rlrotate(cur *tNode) {
+func (tree *vbTree) rlrotate(cur *tNode) *tNode {
 
 	const l = 0
 	const r = 1
 
-	movparent := cur.children[l]
-	mov := movparent.children[r]
+	// 1 right 0 left
+	ln := cur.children[l]
+	lrn := ln.children[r] // 待转换的节点
+	lrln := lrn.children[l]
+	lrrn := lrn.children[r]
 
-	mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
+	ln.children[r] = lrln
+	ln.children[r].parent = ln
 
-	if mov.children[l] != nil {
-		movparent.children[r] = mov.children[l]
-		movparent.children[r].parent = movparent
-	} else {
-		movparent.children[r] = nil
+	if cur.parent != nil {
+		if cur.parent.children[l] == cur {
+			cur.parent.children[l] = lrn
+		} else {
+			cur.parent.children[r] = lrn
+		}
 	}
 
-	if mov.children[r] != nil {
-		mov.children[l] = mov.children[r]
-	} else {
-		mov.children[l] = nil
-	}
+	lrn.children[l] = cur.children[l]
+	lrn.children[l].parent = lrn
 
-	if cur.children[r] != nil {
-		mov.children[r] = cur.children[r]
-		mov.children[r].parent = mov
-	} else {
-		mov.children[r] = nil
-	}
+	lrn.children[l] = cur
+	lrn.children[l].parent = lrn
 
-	cur.children[r] = mov
-	mov.parent = cur
+	cur.children[l] = lrrn
+	cur.children[l].parent = cur
 
-	movparent.size = getChildrenSumSize(movparent) + 1
-	mov.size = getChildrenSumSize(mov) + 1
+	ln.size = getChildrenSumSize(ln) + 1
 	cur.size = getChildrenSumSize(cur) + 1
+	lrn.size = getChildrenSumSize(lrn) + 1
+
+	return lrn
 }
 
 func (tree *vbTree) rrotate3(cur *tNode) {
@@ -744,38 +738,35 @@ func (tree *vbTree) rrotate3(cur *tNode) {
 	mov.size = 1
 }
 
-func (tree *vbTree) rrotate(cur *tNode) {
+func (tree *vbTree) rrotate(cur *tNode) *tNode {
 
 	const l = 0
 	const r = 1
 	// 1 right 0 left
-	mov := cur.children[l]
+	ln := cur.children[l]
+	lrn := ln.children[r] // 待移到另一则的节点
 
-	mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
+	if cur.parent != nil {
+		if cur.parent.children[l] == cur {
+			cur.parent.children[l] = ln
+		} else {
+			cur.parent.children[r] = ln
+		}
+	}
+	ln.parent = cur.parent
 
-	//  mov.children[l]不可能为nil
-	mov.children[l].parent = cur
-	cur.children[l] = mov.children[l]
+	ln.children[r] = cur
+	ln.children[r].parent = ln
 
-	// 解决mov节点孩子转移的问题
-	if mov.children[r] != nil {
-		mov.children[l] = mov.children[r]
-	} else {
-		mov.children[l] = nil
+	cur.children[l] = lrn
+	if lrn != nil {
+		cur.children[l].parent = cur
 	}
 
-	if cur.children[r] != nil {
-		mov.children[r] = cur.children[r]
-		mov.children[r].parent = mov
-	} else {
-		mov.children[r] = nil
-	}
-
-	// 连接转移后的节点 由于mov只是与cur交换值,parent不变
-	cur.children[r] = mov
-
-	mov.size = getChildrenSumSize(mov) + 1
 	cur.size = getChildrenSumSize(cur) + 1
+	ln.size = getChildrenSumSize(ln) + 1
+
+	return ln
 }
 
 func (tree *vbTree) lrotate3(cur *tNode) {
@@ -797,38 +788,35 @@ func (tree *vbTree) lrotate3(cur *tNode) {
 	mov.size = 1
 }
 
-func (tree *vbTree) lrotate(cur *tNode) {
+func (tree *vbTree) lrotate(cur *tNode) *tNode {
 
 	const l = 1
 	const r = 0
-	// 1 right 0 left
-	mov := cur.children[l]
 
-	mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
+	ln := cur.children[l]
+	lrn := ln.children[r] // 待移到另一则的节点
 
-	//  mov.children[l]不可能为nil
-	mov.children[l].parent = cur
-	cur.children[l] = mov.children[l]
+	if cur.parent != nil {
+		if cur.parent.children[l] == cur {
+			cur.parent.children[l] = ln
+		} else {
+			cur.parent.children[r] = ln
+		}
+	}
+	ln.parent = cur.parent
 
-	// 解决mov节点孩子转移的问题
-	if mov.children[r] != nil {
-		mov.children[l] = mov.children[r]
-	} else {
-		mov.children[l] = nil
+	ln.children[r] = cur
+	ln.children[r].parent = ln
+
+	cur.children[l] = lrn
+	if lrn != nil {
+		cur.children[l].parent = cur
 	}
 
-	if cur.children[r] != nil {
-		mov.children[r] = cur.children[r]
-		mov.children[r].parent = mov
-	} else {
-		mov.children[r] = nil
-	}
-
-	// 连接转移后的节点 由于mov只是与cur交换值,parent不变
-	cur.children[r] = mov
-
-	mov.size = getChildrenSumSize(mov) + 1
 	cur.size = getChildrenSumSize(cur) + 1
+	ln.size = getChildrenSumSize(ln) + 1
+
+	return ln
 }
 
 func getChildrenSumSize(cur *tNode) int {
@@ -880,22 +868,87 @@ func (tree *vbTree) fix3Size(cur *tNode, lefts, rigths int) {
 	}
 }
 
-func (tree *vbTree) fixSize(cur *tNode, lefts, rigths int) {
+func (tree *vbTree) fixSize(cur *tNode, lefts, rigths int) *tNode {
 	if lefts > rigths {
 		l := cur.children[0]
 		llsize, lrsize := getChildrenSize(l)
 		if lrsize > llsize {
-			tree.rlrotate(cur)
+			log.Println("rlrotate")
+			return tree.rlrotate(cur)
 		} else {
-			tree.rrotate(cur)
+			log.Println("rrotate")
+			return tree.rrotate(cur)
 		}
 	} else {
 		r := cur.children[1]
 		rlsize, rrsize := getChildrenSize(r)
 		if rlsize > rrsize {
-			tree.lrrotate(cur)
+			log.Println("lrrotate")
+			return tree.lrrotate(cur)
 		} else {
-			tree.lrotate(cur)
+			log.Println("lrotate")
+			return tree.lrotate(cur)
+		}
+	}
+}
+
+func insertNode(parent *tNode, childidx int, newn *tNode) {
+	child := parent.children[childidx]
+	parent.children[childidx] = newn
+	newn.parent = parent
+	// 如果是旋转 还需要把 newn.children[childidx] 转到children的紧邻
+	newn.children[childidx] = child
+}
+
+func replaceNodeNotRoot(oldn, newn *tNode) {
+	if newn.parent == oldn {
+		if oldn.children[0] == newn {
+			oldn.children[0] = nil
+		} else {
+			oldn.children[1] = nil
+		}
+	}
+
+	newn.children[0] = oldn.children[0]
+	newn.children[1] = oldn.children[1]
+	newn.parent = oldn.parent
+
+	if oldn.parent.children[0] == oldn {
+		oldn.parent.children[0] = newn
+	} else {
+		oldn.parent.children[1] = newn
+	}
+}
+
+func replaceNodeMayRoot(oldn, newn *tNode) {
+	if newn.parent == oldn {
+		if oldn.children[0] == newn {
+			oldn.children[0] = nil
+		} else {
+			oldn.children[1] = nil
+		}
+	}
+	newn.children[0] = oldn.children[0]
+	newn.children[1] = oldn.children[1]
+	newn.parent = oldn.parent
+	if oldn.parent != nil {
+		if oldn.parent.children[0] == oldn {
+			oldn.parent.children[0] = newn
+		} else {
+			oldn.parent.children[1] = newn
+		}
+	}
+}
+
+func tailReplaceNode(oldn, newn *tNode) {
+	newn.children[0] = oldn.children[0]
+	newn.children[1] = oldn.children[1]
+	newn.parent = oldn.parent
+	if oldn.parent != nil {
+		if oldn.parent.children[0] == oldn {
+			oldn.parent.children[0] = newn
+		} else {
+			oldn.parent.children[1] = newn
 		}
 	}
 }
diff --git a/priority_queue/vbt_test.go b/priority_queue/vbt_test.go
new file mode 100644
index 0000000..6501702
--- /dev/null
+++ b/priority_queue/vbt_test.go
@@ -0,0 +1,678 @@
+package pqueue
+
+import (
+	"bytes"
+	"encoding/gob"
+	"io/ioutil"
+	"log"
+	"os"
+	"testing"
+
+	"474420502.top/eson/structure/compare"
+	"github.com/huandu/skiplist"
+
+	"github.com/Pallinder/go-randomdata"
+	"github.com/davecgh/go-spew/spew"
+	"github.com/emirpasic/gods/trees/avltree"
+	"github.com/emirpasic/gods/trees/redblacktree"
+)
+
+const CompareSize = 1000000
+const NumberMax = 50000000
+
+func Save(t *testing.T) {
+
+	f, err := os.OpenFile("../l.log", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
+	if err != nil {
+		log.Println(err)
+	}
+	var l []int
+	// for i := 0; len(l) < 1000; i++ {
+	// 	v := randomdata.Number(0, 65535)
+	// 	l = append(l, v)
+	// }
+
+	//m := make(map[int]int)
+	for i := 0; len(l) < CompareSize; i++ {
+		v := randomdata.Number(0, NumberMax)
+		// if _, ok := m[v]; !ok {
+		// 	m[v] = v
+		l = append(l, v)
+		// }
+	}
+
+	var result bytes.Buffer
+	encoder := gob.NewEncoder(&result)
+	encoder.Encode(l)
+	lbytes := result.Bytes()
+	f.Write(lbytes)
+
+}
+
+func loadTestData() []int {
+	data, err := ioutil.ReadFile("../l.log")
+	if err != nil {
+		log.Println(err)
+	}
+	var l []int
+	decoder := gob.NewDecoder(bytes.NewReader(data))
+	decoder.Decode(&l)
+	return l
+}
+
+func TestIndexRange(t *testing.T) {
+	tree := newVBT(compare.Int)
+	l := []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15}
+	for _, v := range l {
+		tree.Put(v)
+	}
+	// [3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50]
+	// t.Error(tree.Values(), tree.Size())
+
+	var result string
+	result = spew.Sprint(tree.IndexRange(0, 5))
+	if result != "[3 7 14 14 14 15] true" {
+		t.Error(result)
+	}
+
+	result = spew.Sprint(tree.IndexRange(2, 5))
+	if result != "[14 14 14 15] true" {
+		t.Error(result)
+	}
+
+	result = spew.Sprint(tree.IndexRange(10, 100))
+	if result != "[30 40 40 40 40 50] false" {
+		t.Error(result)
+	}
+
+	result = spew.Sprint(tree.IndexRange(15, 0)) // size = 16, index max = 15
+	if result != "[50 40 40 40 40 30 21 20 17 16 15 14 14 14 7 3] true" {
+		t.Error(result)
+	}
+
+	result = spew.Sprint(tree.IndexRange(16, 0)) // size = 16, index max = 15
+	if result != "[50 40 40 40 40 30 21 20 17 16 15 14 14 14 7 3] false" {
+		t.Error(result)
+	}
+
+	result = spew.Sprint(tree.IndexRange(5, 1)) // size = 16, index max = 15
+	if result != "[15 14 14 14 7] true" {
+		t.Error(result)
+	}
+
+	result = spew.Sprint(tree.IndexRange(-1, -5)) // size = 16, index max = 15
+	if result != "[50 40 40 40 40] true" {
+		t.Error(result)
+	}
+
+	result = spew.Sprint(tree.IndexRange(-1, -16)) // size = 16, index max = 0 - 15 (-1,-16)
+	if result != "[50 40 40 40 40 30 21 20 17 16 15 14 14 14 7 3] true" {
+		t.Error(result)
+	}
+
+	result = spew.Sprint(tree.IndexRange(-1, -17)) // size = 16, index max = 0 - 15 (-1,-16)
+	if result != "[50 40 40 40 40 30 21 20 17 16 15 14 14 14 7 3] false" {
+		t.Error(result)
+	}
+
+	result = spew.Sprint(tree.IndexRange(-5, -1)) // size = 16, index max = 0 - 15 (-1,-16)
+	if result != "[40 40 40 40 50] true" {
+		t.Error(result)
+	}
+}
+
+func TestGetAround(t *testing.T) {
+	tree := newVBT(compare.Int)
+	for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
+		tree.Put(v)
+	}
+
+	var Result string
+
+	Result = spew.Sprint(tree.GetAround(17))
+	if Result != "[16 17 20]" {
+		t.Error(tree.Values())
+		t.Error("17 is root, tree.GetAround(17)) is error", Result)
+		t.Error(tree.debugString())
+	}
+
+	Result = spew.Sprint(tree.GetAround(3))
+	if Result != "[<nil> 3 7]" {
+		t.Error(tree.Values())
+		t.Error("tree.GetAround(3)) is error", Result)
+		t.Error(tree.debugString())
+	}
+
+	Result = spew.Sprint(tree.GetAround(40))
+	if Result != "[30 40 40]" {
+		t.Error(tree.Values())
+		t.Error("tree.GetAround(40)) is error", Result)
+		t.Error(tree.debugString())
+	}
+
+	Result = spew.Sprint(tree.GetAround(50))
+	if Result != "[40 50 <nil>]" {
+		t.Error(tree.Values())
+		t.Error("tree.GetAround(50)) is error", Result)
+		t.Error(tree.debugString())
+	}
+
+	Result = spew.Sprint(tree.GetAround(18))
+	if Result != "[17 <nil> 20]" {
+		t.Error(tree.Values())
+		t.Error("18 is not in list, tree.GetAround(18)) is error", Result)
+		t.Error(tree.debugString())
+	}
+
+	Result = spew.Sprint(tree.GetAround(5))
+	if Result != "[3 <nil> 7]" {
+		t.Error(tree.Values())
+		t.Error("5 is not in list, tree.GetAround(5)) is error", Result)
+		t.Error(tree.debugString())
+	}
+
+	Result = spew.Sprint(tree.GetAround(2))
+	if Result != "[<nil> <nil> 3]" {
+		t.Error(tree.Values())
+		t.Error("2 is not in list, tree.GetAround(2)) is error", Result)
+		t.Error(tree.debugString())
+	}
+
+	Result = spew.Sprint(tree.GetAround(100))
+	if Result != "[50 <nil> <nil>]" {
+		t.Error(tree.Values())
+		t.Error("50 is not in list, tree.GetAround(50)) is error", Result)
+		t.Error(tree.debugString())
+	}
+
+}
+
+// // for test error case
+
+func TestPutComparatorRandom(t *testing.T) {
+
+	for n := 0; n < 300000; n++ {
+		tree := newVBT(compare.Int)
+		godsavl := avltree.NewWithIntComparator()
+
+		content := ""
+		m := make(map[int]int)
+		for i := 0; len(m) < 10; i++ {
+			v := randomdata.Number(0, 65535)
+			if _, ok := m[v]; !ok {
+				m[v] = v
+				content += spew.Sprint(v) + ","
+				tree.Put(v)
+				godsavl.Put(v, v)
+			}
+		}
+
+		s1 := spew.Sprint(tree.Values())
+		s2 := spew.Sprint(godsavl.Values())
+
+		if s1 != s2 {
+			t.Error(godsavl.String())
+			t.Error(tree.debugString())
+			t.Error(content, n)
+			break
+		}
+	}
+}
+
+func TestGet(t *testing.T) {
+	tree := newVBT(compare.Int)
+	for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
+		tree.Put(v)
+	}
+
+	for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
+		v, ok := tree.Get(v)
+		if !ok {
+			t.Error("the val not found ", v)
+		}
+	}
+
+	if v, ok := tree.Get(10000); ok {
+		t.Error("the val(1000) is not in tree, but is found", v)
+	}
+}
+
+func TestGetRange(t *testing.T) {
+	tree := newVBT(compare.Int)
+	for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
+		tree.Put(v)
+	}
+
+	// t.Error(tree.debugString())
+	// t.Error(tree.getArountNode(20))
+	// t.Error(tree.Values())
+
+	result := tree.GetRange(0, 20)
+	if spew.Sprint(result) != "[1 2 5 6 8 10 13 17]" {
+		t.Error(result)
+	}
+
+	result = tree.GetRange(-5, -1)
+	if spew.Sprint(result) != "[]" {
+		t.Error(result)
+	}
+
+	result = tree.GetRange(7, 20)
+	if spew.Sprint(result) != "[8 10 13 17]" {
+		t.Error(result)
+	}
+
+	result = tree.GetRange(30, 40)
+	if spew.Sprint(result) != "[30 40]" {
+		t.Error(result)
+	}
+
+	result = tree.GetRange(30, 60)
+	if spew.Sprint(result) != "[30 40]" {
+		t.Error(result)
+	}
+
+	result = tree.GetRange(40, 40)
+	if spew.Sprint(result) != "[40]" {
+		t.Error(result)
+	}
+
+	result = tree.GetRange(50, 60)
+	if spew.Sprint(result) != "[]" {
+		t.Error(result)
+	}
+
+	result = tree.GetRange(50, 1)
+	if spew.Sprint(result) != "[40 30 17 13 10 8 6 5 2 1]" {
+		t.Error(result)
+	}
+
+	result = tree.GetRange(30, 20)
+	if spew.Sprint(result) != "[30]" {
+		t.Error(result)
+	}
+
+}
+
+func TestTravalsal(t *testing.T) {
+	tree := newVBT(compare.Int)
+	for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
+		tree.Put(v)
+	}
+
+	i := 0
+	var result []interface{}
+	tree.Traversal(func(v interface{}) bool {
+		result = append(result, v)
+		i++
+		if i >= 10 {
+			return false
+		}
+		return true
+	})
+
+	if spew.Sprint(result) != "[1 2 5 6 8 10 13 17 30 40]" {
+		t.Error(result)
+	}
+
+}
+
+func TestRemoveAll(t *testing.T) {
+ALL:
+	for c := 0; c < 5000; c++ {
+		tree := newVBT(compare.Int)
+		gods := avltree.NewWithIntComparator()
+		var l []int
+		m := make(map[int]int)
+
+		for i := 0; len(l) < 20; i++ {
+			v := randomdata.Number(0, 100000)
+			if _, ok := m[v]; !ok {
+				m[v] = v
+				l = append(l, v)
+				tree.Put(v)
+				gods.Put(v, v)
+			}
+		}
+
+		for i := 0; i < 20; i++ {
+
+			tree.Remove(l[i])
+			gods.Remove(l[i])
+
+			s1 := spew.Sprint(tree.Values())
+			s2 := spew.Sprint(gods.Values())
+			if s1 != s2 {
+				t.Error("avl remove error", "avlsize = ", tree.Size())
+				t.Error(tree.root, i, l[i])
+				t.Error(s1)
+				t.Error(s2)
+				break ALL
+			}
+		}
+	}
+}
+
+func TestRemove(t *testing.T) {
+
+ALL:
+	for N := 0; N < 5000; N++ {
+		tree := newVBT(compare.Int)
+		gods := avltree.NewWithIntComparator()
+
+		var l []int
+		m := make(map[int]int)
+
+		for i := 0; len(l) < 20; i++ {
+			v := randomdata.Number(0, 100)
+			if _, ok := m[v]; !ok {
+				l = append(l, v)
+				m[v] = v
+				tree.Put(v)
+				gods.Put(v, v)
+			}
+		}
+
+		src1 := tree.String()
+		src2 := gods.String()
+
+		for i := 0; i < 20; i++ {
+			tree.Remove(l[i])
+			gods.Remove(l[i])
+			if tree.root != nil && spew.Sprint(gods.Values()) != spew.Sprint(tree.Values()) {
+				t.Error(src1)
+				t.Error(src2)
+				t.Error(tree.debugString())
+				t.Error(gods.String())
+				t.Error(l[i])
+				break ALL
+			}
+		}
+	}
+}
+
+func BenchmarkSkipListGet(b *testing.B) {
+	sl := skiplist.New(skiplist.Int)
+	l := loadTestData()
+	b.N = len(l)
+
+	for _, v := range l {
+		sl.Set(v, v)
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	execCount := 5
+	b.N = len(l) * execCount
+
+	for i := 0; i < execCount; i++ {
+		for _, v := range l {
+			e := sl.Get(v)
+			var result [50]interface{}
+			for i := 0; i < 50 && e != nil; i++ {
+				result[i] = e.Value
+				e = e.Next()
+			}
+		}
+	}
+}
+
+func BenchmarkGetRange(b *testing.B) {
+
+}
+
+func BenchmarkIndexRange(b *testing.B) {
+	tree := newVBT(compare.Int)
+	l := loadTestData()
+	b.N = len(l)
+
+	for _, v := range l {
+		tree.Put(v)
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	execCount := 5
+	b.N = len(l) * execCount
+
+	for i := 0; i < execCount; i++ {
+		for range l {
+			tree.IndexRange(i, i+49)
+		}
+	}
+}
+
+func BenchmarkSkipListSet(b *testing.B) {
+
+	l := loadTestData()
+
+	execCount := 1
+	b.N = len(l) * execCount
+
+	for i := 0; i < execCount; i++ {
+		sl := skiplist.New(skiplist.Int)
+		for _, v := range l {
+			sl.Set(v, v)
+		}
+	}
+}
+
+func BenchmarkIterator(b *testing.B) {
+	tree := newVBT(compare.Int)
+
+	l := loadTestData()
+	b.N = len(l)
+
+	for _, v := range l {
+		tree.Put(v)
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+	iter := tree.Iterator()
+	b.N = 0
+	for iter.Next() {
+		b.N++
+	}
+	for iter.Prev() {
+		b.N++
+	}
+	for iter.Next() {
+		b.N++
+	}
+	b.Log(b.N, len(l))
+}
+
+func BenchmarkRemove(b *testing.B) {
+	tree := newVBT(compare.Int)
+
+	l := loadTestData()
+
+	b.N = len(l)
+	for _, v := range l {
+		tree.Put(v)
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	for i := 0; i < len(l); i++ {
+		tree.Remove(l[i])
+	}
+}
+
+func BenchmarkGodsRemove(b *testing.B) {
+	tree := avltree.NewWithIntComparator()
+
+	l := loadTestData()
+
+	b.N = len(l)
+	for _, v := range l {
+		tree.Put(v, v)
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	for i := 0; i < len(l); i++ {
+		tree.Remove(l[i])
+	}
+}
+
+func BenchmarkGodsRBRemove(b *testing.B) {
+	tree := redblacktree.NewWithIntComparator()
+
+	l := loadTestData()
+
+	b.N = len(l)
+	for _, v := range l {
+		tree.Put(v, v)
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	for i := 0; i < len(l); i++ {
+		tree.Remove(l[i])
+	}
+}
+
+func BenchmarkGet(b *testing.B) {
+
+	tree := newVBT(compare.Int)
+
+	l := loadTestData()
+	b.N = len(l)
+	for i := 0; i < b.N; i++ {
+		tree.Put(l[i])
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	execCount := 10
+	b.N = len(l) * execCount
+
+	for i := 0; i < execCount; i++ {
+		for _, v := range l {
+			tree.Get(v)
+		}
+	}
+}
+
+func BenchmarkGodsRBGet(b *testing.B) {
+	tree := redblacktree.NewWithIntComparator()
+
+	l := loadTestData()
+	b.N = len(l)
+	for i := 0; i < b.N; i++ {
+		tree.Put(l[i], i)
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	execCount := 10
+	b.N = len(l) * execCount
+
+	for i := 0; i < execCount; i++ {
+		for _, v := range l {
+			tree.Get(v)
+		}
+	}
+}
+
+func BenchmarkGodsAvlGet(b *testing.B) {
+	tree := avltree.NewWithIntComparator()
+
+	l := loadTestData()
+	b.N = len(l)
+	for i := 0; i < b.N; i++ {
+		tree.Put(l[i], i)
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	execCount := 10
+	b.N = len(l) * execCount
+
+	for i := 0; i < execCount; i++ {
+		for _, v := range l {
+			tree.Get(v)
+		}
+	}
+}
+
+func BenchmarkPut(b *testing.B) {
+	l := loadTestData()
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	execCount := 10
+	b.N = len(l) * execCount
+	for i := 0; i < execCount; i++ {
+		tree := newVBT(compare.Int)
+		for _, v := range l {
+			tree.Put(v)
+		}
+	}
+}
+
+func TestPutStable(t *testing.T) {
+	tree := newVBT(compare.Int)
+	for i := 0; i < 10; i++ {
+		v := randomdata.Number(0, 100)
+		tree.Put(v)
+		t.Error(tree.debugString(), v)
+	}
+
+}
+
+func BenchmarkIndex(b *testing.B) {
+	tree := newVBT(compare.Int)
+
+	l := loadTestData()
+	b.N = len(l)
+	for i := 0; i < b.N; i++ {
+		tree.Put(l[i])
+	}
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	for i := 0; i < b.N; i++ {
+		tree.Index(i)
+	}
+}
+
+func BenchmarkGodsRBPut(b *testing.B) {
+	tree := redblacktree.NewWithIntComparator()
+
+	l := loadTestData()
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	b.N = len(l)
+	for _, v := range l {
+		tree.Put(v, v)
+	}
+}
+
+func BenchmarkGodsPut(b *testing.B) {
+	tree := avltree.NewWithIntComparator()
+
+	l := loadTestData()
+
+	b.ResetTimer()
+	b.StartTimer()
+
+	b.N = len(l)
+	for _, v := range l {
+		tree.Put(v, v)
+	}
+}