From c6b06a9c3bfceafee170c76411bcfae18a756133 Mon Sep 17 00:00:00 2001 From: huangsimin Date: Thu, 21 Mar 2019 15:27:08 +0800 Subject: [PATCH] =?UTF-8?q?getAround=20=E5=AE=8C=E7=BE=8E=E5=AE=8C?= =?UTF-8?q?=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- avl/avl_test.go | 2 +- avlindex/avlindex.go | 211 +++++++-- avlindex/avlindex_test.go | 153 +++++-- sbt/iterator.go | 215 +++++++++ sbt/sbt.go | 904 ++++++++++++++++++++++++++++++++++++++ sbt/sbt_test.go | 649 +++++++++++++++++++++++++++ 6 files changed, 2058 insertions(+), 76 deletions(-) create mode 100644 sbt/iterator.go create mode 100644 sbt/sbt.go create mode 100644 sbt/sbt_test.go diff --git a/avl/avl_test.go b/avl/avl_test.go index baf3551..b6970bc 100644 --- a/avl/avl_test.go +++ b/avl/avl_test.go @@ -128,7 +128,7 @@ func TestGetAround(t *testing.T) { } if spew.Sprint(avl.GetAround(50)) != "[ 50 40]" { - t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(50))) + t.Error("avl.GetAround(50)) is error", spew.Sprint(avl.GetAround(50))) } } diff --git a/avlindex/avlindex.go b/avlindex/avlindex.go index 0ca3586..67ca76c 100644 --- a/avlindex/avlindex.go +++ b/avlindex/avlindex.go @@ -186,7 +186,7 @@ func (avl *Tree) Values() []interface{} { return result } -func (avl *Tree) GetRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1 +func (avl *Tree) IndexRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1 if idx1^idx2 < 0 { if idx1 < 0 { @@ -244,16 +244,20 @@ func (avl *Tree) GetRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 return nil, false } -func (avl *Tree) Get(key interface{}) (interface{}, bool) { - n, ok := avl.GetNode(key) +// func (avl *Tree) GetRange(v1, v2 interface{}) { +// avl.getArountNode(v1) +// } + +func (avl *Tree) Get(value interface{}) (interface{}, bool) { + n, ok := avl.GetNode(value) if ok { return n.value, true } return n, false } -func (avl *Tree) GetAround(key interface{}) (result [3]interface{}) { - an := avl.GetAroundNode(key) +func (avl *Tree) GetAround(value interface{}) (result [3]interface{}) { + an := avl.getArountNode(value) for i, n := range an { if n != nil { result[i] = n.value @@ -262,38 +266,174 @@ func (avl *Tree) GetAround(key interface{}) (result [3]interface{}) { return } -func (avl *Tree) GetAroundNode(value interface{}) (result [3]*Node) { +func (avl *Tree) getArountNode(value interface{}) (result [3]*Node) { + var last *Node + var lastc int - if cur, ok := avl.GetNode(value); ok { - - var iter *Iterator - - iter = NewIterator(cur) - iter.curPushPrevStack(iter.up) - iter.up = iter.getPrevUp(iter.up) - - if v, ok := iter.tstack.Pop(); ok { - result[0] = v.(*Node) - // iter.curPushPrevStack(iter.cur) - } else { - result[0] = iter.up + for n := avl.root; n != nil; { + last = n + c := avl.comparator(value, n.value) + switch c { + case -1: + n = n.children[0] + lastc = c + case 1: + n = n.children[1] + lastc = c + case 0: + result[1] = n + n = nil + default: + panic("Get comparator only is allowed in -1, 0, 1") } - - iter = NewIterator(cur) - iter.curPushNextStack(iter.up) - iter.up = iter.getNextUp(iter.up) - - if v, ok := iter.tstack.Pop(); ok { - result[2] = v.(*Node) - // iter.curPushNextStack(iter.cur) - } else { - result[2] = iter.up - } - - result[1] = cur } + + switch lastc { + case 1: + const il = 0 + const ir = 1 + + if result[1] == nil { + result[0] = last + } else { + l := result[1].children[il] + r := result[1].children[ir] + + if l == nil { + result[0] = result[1].parent + } else { + for l.children[ir] != nil { + l = l.children[ir] + } + result[0] = l + } + + if r == nil { + + parent := result[1].parent + for ; parent != nil && parent.parent != nil; parent = parent.parent { + child := getRelationship(parent) + if child == (-lastc+2)/2 { // child 与 comparator 后左右的关系 + result[2] = parent.parent + break + } + } + + } else { + for r.children[il] != nil { + r = r.children[il] + } + result[2] = r + } + } + + case -1: + + const il = 1 + const ir = 0 + + if result[1] == nil { + result[2] = last + } else { + + l := result[1].children[il] + r := result[1].children[ir] + + if l == nil { + result[2] = result[1].parent + } else { + for l.children[ir] != nil { + l = l.children[ir] + } + result[2] = l + } + + if r == nil { + + parent := result[1].parent + for ; parent != nil && parent.parent != nil; parent = parent.parent { + child := getRelationship(parent) + if child == (-lastc+2)/2 { // child 与 comparator 后左右的关系 + result[0] = parent.parent + break + } + } + + } else { + + for r.children[il] != nil { + r = r.children[il] + } + result[0] = r + + } + } + case 0: + + const il = 0 + const ir = 1 + + if result[1] == nil { + return + } + + l := result[1].children[il] + r := result[1].children[ir] + + if l == nil { + result[0] = nil + } else { + for l.children[ir] != nil { + l = l.children[ir] + } + result[0] = l + } + + if r == nil { + result[2] = nil + } else { + for r.children[il] != nil { + r = r.children[il] + } + result[2] = r + } + } + return } + +// func (avl *Tree) GetAroundNode(value interface{}) (result [3]*Node) { + +// if cur, ok := avl.GetNode(value); ok { + +// var iter *Iterator + +// iter = NewIterator(cur) +// iter.curPushPrevStack(iter.up) +// iter.up = iter.getPrevUp(iter.up) + +// if v, ok := iter.tstack.Pop(); ok { +// result[2] = v.(*Node) +// // iter.curPushPrevStack(iter.cur) +// } else { +// result[2] = iter.up +// } + +// iter = NewIterator(cur) +// iter.curPushNextStack(iter.up) +// iter.up = iter.getNextUp(iter.up) + +// if v, ok := iter.tstack.Pop(); ok { +// result[0] = v.(*Node) +// // iter.curPushNextStack(iter.cur) +// } else { +// result[0] = iter.up +// } + +// result[1] = cur +// } +// return +// } func (avl *Tree) GetNode(value interface{}) (*Node, bool) { for n := avl.root; n != nil; { @@ -338,7 +478,7 @@ func (avl *Tree) Put(value interface{}) { return } - if cur.size > 9 { + if cur.size > 8 { ls, rs := cur.children[0].size, cur.children[1].size factor := cur.size / 10 // or factor = 1 if rs >= ls*2+factor || ls >= rs*2+factor { @@ -773,9 +913,10 @@ func getSize(cur *Node) int { func (avl *Tree) fixRemoveHeight(cur *Node) { for cur != nil { cur.size-- - if cur.size > 9 { + if cur.size > 8 { ls, rs := cur.children[0].size, cur.children[1].size - if rs >= ls*2 || ls >= rs*2 { + factor := cur.size / 10 // or factor = 1 + if rs >= ls*2+factor || ls >= rs*2+factor { avl.fixPutHeight(cur, ls, rs) } } diff --git a/avlindex/avlindex_test.go b/avlindex/avlindex_test.go index 3235ed3..462f114 100644 --- a/avlindex/avlindex_test.go +++ b/avlindex/avlindex_test.go @@ -74,7 +74,7 @@ func TestIterator(t *testing.T) { } -func TestGetRange(t *testing.T) { +func TestIndexRange(t *testing.T) { tree := New(utils.IntComparator) l := []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} for _, v := range l { @@ -84,79 +84,121 @@ func TestGetRange(t *testing.T) { // t.Error(tree.Values(), tree.Size()) var result string - result = spew.Sprint(tree.GetRange(0, 5)) + result = spew.Sprint(tree.IndexRange(0, 5)) if result != "[3 7 14 14 14 15] true" { t.Error(result) } - result = spew.Sprint(tree.GetRange(2, 5)) + result = spew.Sprint(tree.IndexRange(2, 5)) if result != "[14 14 14 15] true" { t.Error(result) } - result = spew.Sprint(tree.GetRange(10, 100)) + result = spew.Sprint(tree.IndexRange(10, 100)) if result != "[30 40 40 40 40 50] false" { t.Error(result) } - result = spew.Sprint(tree.GetRange(15, 0)) // size = 16, index max = 15 + 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.GetRange(16, 0)) // size = 16, index max = 15 + 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.GetRange(5, 1)) // size = 16, index max = 15 + 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.GetRange(-1, -5)) // size = 16, index max = 15 + 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.GetRange(-1, -16)) // size = 16, index max = 0 - 15 (-1,-16) + 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.GetRange(-1, -17)) // size = 16, index max = 0 - 15 (-1,-16) + 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.GetRange(-5, -1)) // size = 16, index max = 0 - 15 (-1,-16) + 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) { - avl := New(utils.IntComparator) + tree := New(utils.IntComparator) for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} { - avl.Put(v) + tree.Put(v) } var Result string - Result = spew.Sprint(avl.GetAround(3)) - if Result != "[7 3 ]" { - t.Error("avl.GetAround(3)) is error", Result) + 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(avl.GetAround(40)) - if Result != "[40 40 30]" { - t.Error("avl.GetAround(40)) is error", Result) + Result = spew.Sprint(tree.GetAround(3)) + if Result != "[ 3 7]" { + t.Error(tree.Values()) + t.Error("tree.GetAround(3)) is error", Result) + t.Error(tree.debugString()) } - Result = spew.Sprint(avl.GetAround(50)) - if Result != "[ 50 40]" { - t.Error("avl.GetAround(50)) is error", Result) + 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 ]" { + t.Error(tree.Values()) + t.Error("tree.GetAround(50)) is error", Result) + t.Error(tree.debugString()) + } + + Result = spew.Sprint(tree.GetAround(18)) + if Result != "[ 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 ]" { + 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 != "[ 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 ]" { + 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 @@ -352,7 +394,7 @@ func BenchmarkGetRange(b *testing.B) { for i := 0; i < execCount; i++ { for range l { - tree.GetRange(i, i+49) + tree.IndexRange(i, i+49) } } } @@ -538,25 +580,56 @@ func BenchmarkPut(b *testing.B) { func TestPutStable(t *testing.T) { // l := []int{14, 18, 20, 21, 22, 23, 19} - var l []int - for i := 0; len(l) < 10; i++ { - l = append(l, randomdata.Number(0, 65)) - } + for n := 0; n < 1000000; n++ { + var l []int + l = append(l, 60, 5, 15) + for i := 0; len(l) < 11; i++ { + l = append(l, randomdata.Number(3, 69)) + } - avl := New(utils.IntComparator) - for _, v := range l { - avl.Put(v) - t.Error(avl.debugString(), v) - } - t.Error(avl.Values()) - for _, v := range []int{10, 0, 9, 5, -11, -10, -1, -5} { - t.Error(avl.Index(v)) - } + avl := New(utils.IntComparator) + for _, v := range l { + avl.Put(v) + } + result := avl.getArountNode(60) - avl.RemoveIndex(4) - t.Error(avl.Index(4)) - t.Error(avl.Values()) - t.Error(avl.debugString()) + if result[2] == nil && avl.indexNode(-1) != result[1] { + t.Error(avl.debugString()) + t.Error(avl.Values()) + t.Error(result) + } + + result = avl.getArountNode(5) + if result[0] == nil && avl.indexNode(0) != result[1] { + t.Error(avl.debugString()) + t.Error(avl.Values()) + t.Error(result) + } + + result = avl.getArountNode(2) + if result[2] == nil && avl.indexNode(0) != result[2] { + t.Error(avl.debugString()) + t.Error(avl.Values()) + t.Error(result) + } + + result = avl.getArountNode(70) + if result[0] == nil && avl.indexNode(-1) != result[0] { + t.Error(avl.debugString()) + t.Error(avl.Values()) + t.Error(result) + } + + } + // for _, v := range []int{10, 0, 9, 5, -11, -10, -1, -5} { + // t.Error(avl.Index(v)) + // // t.Error(avl.debugString()) + // } + + // avl.RemoveIndex(4) + // t.Error(avl.Index(4)) + // t.Error(avl.Values()) + // t.Error(avl.debugString()) // t.Error(len(l), avl.debugString(), "\n", "-----------") // 3 6(4) } diff --git a/sbt/iterator.go b/sbt/iterator.go new file mode 100644 index 0000000..5e525fb --- /dev/null +++ b/sbt/iterator.go @@ -0,0 +1,215 @@ +package avlindex + +import ( + "474420502.top/eson/structure/lastack" +) + +type Iterator struct { + dir int + up *Node + cur *Node + tstack *lastack.Stack + // curnext *Node +} + +func initIterator(avltree *Tree) *Iterator { + iter := &Iterator{tstack: lastack.New()} + iter.up = avltree.root + return iter +} + +func NewIterator(n *Node) *Iterator { + iter := &Iterator{tstack: lastack.New()} + iter.up = n + return iter +} + +func (iter *Iterator) Value() interface{} { + return iter.cur.value +} + +func (iter *Iterator) Left() bool { + if iter.cur.children[0] != nil { + iter.dir = 0 + iter.cur = iter.cur.children[0] + return true + } + return false +} + +func (iter *Iterator) Right() bool { + if iter.cur.children[1] != nil { + iter.dir = 0 + iter.cur = iter.cur.children[1] + return true + } + return false +} + +func GetPrev(cur *Node, idx int) *Node { + + iter := NewIterator(cur) + iter.curPushPrevStack(iter.up) + iter.up = iter.getPrevUp(iter.up) + + for i := 0; i < idx; i++ { + + if iter.tstack.Size() == 0 { + if iter.up == nil { + return nil + } + iter.tstack.Push(iter.up) + iter.up = iter.getPrevUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + if i == idx-1 { + return iter.cur + } + iter.curPushPrevStack(iter.cur) + } else { + return nil + } + } + + return cur +} + +func (iter *Iterator) Prev() (result bool) { + + if iter.dir > -1 { + if iter.dir == 1 && iter.cur != nil { + iter.tstack.Clear() + iter.curPushPrevStack(iter.cur) + iter.up = iter.getPrevUp(iter.cur) + } + iter.dir = -1 + } + + if iter.tstack.Size() == 0 { + if iter.up == nil { + return false + } + iter.tstack.Push(iter.up) + iter.up = iter.getPrevUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + iter.curPushPrevStack(iter.cur) + return true + } + + return false +} +func GetNext(cur *Node, idx int) *Node { + + iter := NewIterator(cur) + iter.curPushNextStack(iter.up) + iter.up = iter.getNextUp(iter.up) + + for i := 0; i < idx; i++ { + + if iter.tstack.Size() == 0 { + if iter.up == nil { + return nil + } + iter.tstack.Push(iter.up) + iter.up = iter.getNextUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + if i == idx-1 { + return iter.cur + } + iter.curPushNextStack(iter.cur) + } else { + return nil + } + } + + return cur +} + +func (iter *Iterator) Next() (result bool) { + + if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev) + if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈 + iter.tstack.Clear() + iter.curPushNextStack(iter.cur) // 把当前cur计算的逆向回朔 + iter.up = iter.getNextUp(iter.cur) // cur 寻找下个要计算up + } + iter.dir = 1 + } + + // 如果栈空了, 把up的递归计算入栈, 重新计算 下次的up值 + if iter.tstack.Size() == 0 { + if iter.up == nil { + return false + } + iter.tstack.Push(iter.up) + iter.up = iter.getNextUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + iter.curPushNextStack(iter.cur) + return true + } + + // 如果再次计算的栈为空, 则只能返回false + return false +} + +func getRelationship(cur *Node) int { + if cur.parent.children[1] == cur { + return 1 + } + return 0 +} + +func (iter *Iterator) getNextUp(cur *Node) *Node { + for cur.parent != nil { + if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序 + return cur.parent + } + cur = cur.parent + } + return nil +} + +func (iter *Iterator) curPushNextStack(cur *Node) { + next := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值 + + if next != nil { + iter.tstack.Push(next) + for next.children[1] != nil { + next = next.children[1] + iter.tstack.Push(next) // 入栈 用于回溯 + } + } +} + +func (iter *Iterator) getPrevUp(cur *Node) *Node { + for cur.parent != nil { + if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序 + return cur.parent + } + cur = cur.parent + } + return nil +} + +func (iter *Iterator) curPushPrevStack(cur *Node) { + prev := cur.children[1] + + if prev != nil { + iter.tstack.Push(prev) + for prev.children[0] != nil { + prev = prev.children[0] + iter.tstack.Push(prev) + } + } +} diff --git a/sbt/sbt.go b/sbt/sbt.go new file mode 100644 index 0000000..2ded8e4 --- /dev/null +++ b/sbt/sbt.go @@ -0,0 +1,904 @@ +package avlindex + +import ( + "log" + + "github.com/davecgh/go-spew/spew" + + "github.com/emirpasic/gods/utils" +) + +type Node struct { + children [2]*Node + parent *Node + size int + value interface{} +} + +func (n *Node) String() string { + if n == nil { + return "nil" + } + + p := "nil" + if n.parent != nil { + p = spew.Sprint(n.parent.value) + } + return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.size) + ")" +} + +type Tree struct { + root *Node + comparator utils.Comparator +} + +func New(comparator utils.Comparator) *Tree { + return &Tree{comparator: comparator} +} + +func (avl *Tree) String() string { + str := "AVLTree\n" + if avl.root == nil { + return str + "nil" + } + output(avl.root, "", true, &str) + return str +} + +func (avl *Tree) Iterator() *Iterator { + return initIterator(avl) +} + +func (avl *Tree) Size() int { + if avl.root == nil { + return 0 + } + return avl.root.size +} + +func (avl *Tree) indexNode(idx int) *Node { + cur := avl.root + if idx >= 0 { + for cur != nil { + ls := getSize(cur.children[0]) + if idx == ls { + return cur + } else if idx < ls { + cur = cur.children[0] + } else { + idx = idx - ls - 1 + cur = cur.children[1] + } + } + } else { + idx = -idx - 1 + for cur != nil { + rs := getSize(cur.children[1]) + if idx == rs { + return cur + } else if idx < rs { + cur = cur.children[1] + } else { + idx = idx - rs - 1 + cur = cur.children[0] + } + } + } + return nil +} + +func (avl *Tree) Index(idx int) (interface{}, bool) { + n := avl.indexNode(idx) + if n != nil { + return n.value, true + } + return nil, false +} + +func (avl *Tree) RemoveIndex(idx int) bool { + n := avl.indexNode(idx) + if n != nil { + avl.removeNode(n) + return true + } + return false +} + +func (avl *Tree) removeNode(n *Node) { + if avl.root.size == 1 { + avl.root = nil + // return n + return + } + + ls, rs := getChildrenSize(n) + if ls == 0 && rs == 0 { + p := n.parent + p.children[getRelationship(n)] = nil + avl.fixRemoveHeight(p) + // return n + return + } + + var cur *Node + if ls > rs { + cur = n.children[0] + for cur.children[1] != nil { + cur = cur.children[1] + } + + cleft := cur.children[0] + cur.parent.children[getRelationship(cur)] = cleft + if cleft != nil { + cleft.parent = cur.parent + } + + } else { + cur = n.children[1] + for cur.children[0] != nil { + cur = cur.children[0] + } + + cright := cur.children[1] + cur.parent.children[getRelationship(cur)] = cright + + if cright != nil { + cright.parent = cur.parent + } + } + + cparent := cur.parent + // 修改为interface 交换 + n.value, cur.value = cur.value, n.value + + // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 + if cparent == n { + avl.fixRemoveHeight(n) + } else { + avl.fixRemoveHeight(cparent) + } + + // return cur + return +} + +func (avl *Tree) Remove(key interface{}) bool { + + if n, ok := avl.GetNode(key); ok { + avl.removeNode(n) + return true + } + // return nil + return false +} + +// Values 返回先序遍历的值 +func (avl *Tree) Values() []interface{} { + mszie := 0 + if avl.root != nil { + mszie = avl.root.size + } + result := make([]interface{}, 0, mszie) + avl.Traversal(func(v interface{}) bool { + result = append(result, v) + return true + }, LDR) + return result +} + +func (avl *Tree) IndexRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1 + + if idx1^idx2 < 0 { + if idx1 < 0 { + idx1 = avl.root.size + idx1 - 1 + } else { + idx2 = avl.root.size + idx2 - 1 + } + } + + if idx1 > idx2 { + ok = true + if idx1 >= avl.root.size { + idx1 = avl.root.size - 1 + ok = false + } + + n := avl.indexNode(idx1) + iter := NewIterator(n) + result = make([]interface{}, 0, idx1-idx2) + for i := idx2; i <= idx1; i++ { + if iter.Next() { + result = append(result, iter.Value()) + } else { + ok = false + return + } + } + + return + + } else { + ok = true + if idx2 >= avl.root.size { + idx2 = avl.root.size - 1 + ok = false + } + + if n := avl.indexNode(idx1); n != nil { + iter := NewIterator(n) + result = make([]interface{}, 0, idx2-idx1) + for i := idx1; i <= idx2; i++ { + if iter.Prev() { + result = append(result, iter.Value()) + } else { + ok = false + return + } + } + + return + } + + } + + return nil, false +} + +func (avl *Tree) Get(key interface{}) (interface{}, bool) { + n, ok := avl.GetNode(key) + if ok { + return n.value, true + } + return n, false +} + +func (avl *Tree) GetAround(key interface{}) (result [3]interface{}) { + an := avl.GetAroundNode(key) + for i, n := range an { + if n != nil { + result[i] = n.value + } + } + return +} + +func (avl *Tree) GetAroundNode(value interface{}) (result [3]*Node) { + + if cur, ok := avl.GetNode(value); ok { + + var iter *Iterator + + iter = NewIterator(cur) + iter.curPushPrevStack(iter.up) + iter.up = iter.getPrevUp(iter.up) + + if v, ok := iter.tstack.Pop(); ok { + result[0] = v.(*Node) + // iter.curPushPrevStack(iter.cur) + } else { + result[0] = iter.up + } + + iter = NewIterator(cur) + iter.curPushNextStack(iter.up) + iter.up = iter.getNextUp(iter.up) + + if v, ok := iter.tstack.Pop(); ok { + result[2] = v.(*Node) + // iter.curPushNextStack(iter.cur) + } else { + result[2] = iter.up + } + + result[1] = cur + } + return +} +func (avl *Tree) GetNode(value interface{}) (*Node, bool) { + + for n := avl.root; n != nil; { + switch c := avl.comparator(value, n.value); c { + case -1: + n = n.children[0] + case 1: + n = n.children[1] + case 0: + return n, true + default: + panic("Get comparator only is allowed in -1, 0, 1") + } + } + return nil, false +} + +func (avl *Tree) Put(value interface{}) { + + node := &Node{value: value, size: 1} + if avl.root == nil { + avl.root = node + return + } + + cur := avl.root + parent := cur.parent + child := -1 + + for { + + if cur == nil { + parent.children[child] = node + node.parent = parent + + fixed := parent.parent + fsize := getSize(fixed) + if fsize == 3 { + lefts, rigths := getChildrenSize(fixed) + avl.fix3PutHeight(fixed, lefts, rigths) + } + return + } + + if cur.size > 9 { + ls, rs := cur.children[0].size, cur.children[1].size + factor := cur.size / 10 // or factor = 1 + if rs >= ls*2+factor || ls >= rs*2+factor { + avl.fixPutHeight(cur, ls, rs) + } + } + + cur.size++ + parent = cur + c := avl.comparator(value, cur.value) + child = (c + 2) / 2 + cur = cur.children[child] + } +} + +type TraversalMethod int + +const ( + // L = left R = right D = Value(dest) + _ TraversalMethod = iota + //DLR 先值 然后左递归 右递归 下面同理 + DLR + //LDR 先从左边有序访问到右边 从小到大 + LDR + // LRD 同理 + LRD + + // DRL 同理 + DRL + + // RDL 先从右边有序访问到左边 从大到小 + RDL + + // RLD 同理 + RLD +) + +// Traversal 遍历的方法 +func (avl *Tree) Traversal(every func(v interface{}) bool, traversalMethod ...interface{}) { + if avl.root == nil { + return + } + + method := LDR + if len(traversalMethod) != 0 { + method = traversalMethod[0].(TraversalMethod) + } + + switch method { + case DLR: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !every(cur.value) { + return false + } + if !traverasl(cur.children[0]) { + return false + } + if !traverasl(cur.children[1]) { + return false + } + return true + } + traverasl(avl.root) + case LDR: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !traverasl(cur.children[0]) { + log.Println(cur) + return false + } + if !every(cur.value) { + return false + } + if !traverasl(cur.children[1]) { + return false + } + return true + } + traverasl(avl.root) + case LRD: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !traverasl(cur.children[0]) { + return false + } + if !traverasl(cur.children[1]) { + return false + } + if !every(cur.value) { + return false + } + return true + } + traverasl(avl.root) + case DRL: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !every(cur.value) { + return false + } + if !traverasl(cur.children[0]) { + return false + } + if !traverasl(cur.children[1]) { + return false + } + return true + } + traverasl(avl.root) + case RDL: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !traverasl(cur.children[1]) { + return false + } + if !every(cur.value) { + return false + } + if !traverasl(cur.children[0]) { + return false + } + return true + } + traverasl(avl.root) + case RLD: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !traverasl(cur.children[1]) { + return false + } + if !traverasl(cur.children[0]) { + return false + } + if !every(cur.value) { + return false + } + return true + } + traverasl(avl.root) + } +} + +func (avl *Tree) lrrotate3(cur *Node) { + const l = 1 + const r = 0 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + cur.children[r] = mov + mov.parent = cur + + cur.children[l] = movparent + movparent.children[r] = nil + + cur.children[r] = mov + mov.parent = cur + + // cur.size = 3 + // cur.children[r].size = 1 + cur.children[l].size = 1 +} + +func (avl *Tree) lrrotate(cur *Node) { + + const l = 1 + const r = 0 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + 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 mov.children[r] != nil { + mov.children[l] = mov.children[r] + //mov.children[l].child = l + } else { + mov.children[l] = nil + } + + if cur.children[r] != nil { + mov.children[r] = cur.children[r] + mov.children[r].parent = mov + } else { + mov.children[r] = nil + } + + cur.children[r] = mov + mov.parent = cur + + // cur.size = 3 + // cur.children[0].size = 1 + // cur.children[1].size = 1 + + movparent.size = getChildrenSumSize(movparent) + 1 + mov.size = getChildrenSumSize(mov) + 1 + cur.size = getChildrenSumSize(cur) + 1 + + // mov.height = getMaxChildrenHeight(mov) + 1 + // movparent.height = getMaxChildrenHeight(movparent) + 1 + // cur.height = getMaxChildrenHeight(cur) + 1 +} + +func (avl *Tree) rlrotate3(cur *Node) { + const l = 0 + const r = 1 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + cur.children[r] = mov + mov.parent = cur + + cur.children[l] = movparent + movparent.children[r] = nil + + cur.children[r] = mov + mov.parent = cur + + // cur.size = 3 + // cur.children[r].size = 1 + cur.children[l].size = 1 +} + +func (avl *Tree) rlrotate(cur *Node) { + + const l = 0 + const r = 1 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + if mov.children[l] != nil { + movparent.children[r] = mov.children[l] + movparent.children[r].parent = movparent + } else { + movparent.children[r] = nil + } + + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + } else { + mov.children[l] = nil + } + + if cur.children[r] != nil { + mov.children[r] = cur.children[r] + mov.children[r].parent = mov + } else { + mov.children[r] = nil + } + + cur.children[r] = mov + mov.parent = cur + + movparent.size = getChildrenSumSize(movparent) + 1 + mov.size = getChildrenSumSize(mov) + 1 + cur.size = getChildrenSumSize(cur) + 1 +} + +func (avl *Tree) rrotate3(cur *Node) { + const l = 0 + const r = 1 + // 1 right 0 left + mov := cur.children[l] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + cur.children[r] = mov + mov.size = 1 + + cur.children[l] = mov.children[l] + cur.children[l].parent = cur + + mov.children[l] = nil + + mov.size = 1 +} + +func (avl *Tree) rrotate(cur *Node) { + + const l = 0 + const r = 1 + // 1 right 0 left + mov := cur.children[l] + + // lsize, rsize := getChildrenHeight(cur) + // movrsize := getSize(mov.children[r]) + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + // mov.children[l]不可能为nil + + mov.children[l].parent = cur + cur.children[l] = mov.children[l] + + // 解决mov节点孩子转移的问题 + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + } else { + mov.children[l] = nil + } + + 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 + + // cur.size = 3 + // cur.children[0].size = 1 + // cur.children[1].size = 1 + + mov.size = getChildrenSumSize(mov) + 1 + cur.size = getChildrenSumSize(cur) + 1 + // cur.height = getMaxChildrenHeight(cur) + 1 +} + +func (avl *Tree) lrotate3(cur *Node) { + const l = 1 + const r = 0 + // 1 right 0 left + mov := cur.children[l] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + cur.children[r] = mov + mov.size = 1 + + cur.children[l] = mov.children[l] + cur.children[l].parent = cur + + mov.children[l] = nil + + mov.size = 1 +} + +func (avl *Tree) lrotate(cur *Node) { + + const l = 1 + const r = 0 + // 1 right 0 left + mov := cur.children[l] + + // lsize, rsize := getChildrenHeight(cur) + // movrsize := getSize(mov.children[r]) + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + // mov.children[l]不可能为nil + + mov.children[l].parent = cur + cur.children[l] = mov.children[l] + + // 解决mov节点孩子转移的问题 + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + } else { + mov.children[l] = nil + } + + 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 + + // cur.size = 3 + // cur.children[0].size = 1 + // cur.children[1].size = 1 + + mov.size = getChildrenSumSize(mov) + 1 + cur.size = getChildrenSumSize(cur) + 1 +} + +func getChildrenSumSize(cur *Node) int { + return getSize(cur.children[0]) + getSize(cur.children[1]) +} + +func getChildrenSize(cur *Node) (int, int) { + return getSize(cur.children[0]), getSize(cur.children[1]) +} + +func getSize(cur *Node) int { + if cur == nil { + return 0 + } + return cur.size +} + +func (avl *Tree) fixRemoveHeight(cur *Node) { + for cur != nil { + cur.size-- + if cur.size > 9 { + ls, rs := cur.children[0].size, cur.children[1].size + if rs >= ls*2 || ls >= rs*2 { + avl.fixPutHeight(cur, ls, rs) + } + } + cur = cur.parent + } +} + +func (avl *Tree) fix3PutHeight(cur *Node, lefts, rigths int) { + if lefts > rigths { + l := cur.children[0] + llsize, lrsize := getChildrenSize(l) + if lrsize > llsize { + avl.rlrotate3(cur) + } else { + avl.rrotate3(cur) + } + } else { + r := cur.children[1] + rlsize, rrsize := getChildrenSize(r) + if rlsize > rrsize { + avl.lrrotate3(cur) + } else { + avl.lrotate3(cur) + } + } +} + +func (avl *Tree) fixPutHeight(cur *Node, lefts, rigths int) { + if lefts > rigths { + l := cur.children[0] + llsize, lrsize := getChildrenSize(l) + if lrsize > llsize { + avl.rlrotate(cur) + } else { + avl.rrotate(cur) + } + } else { + r := cur.children[1] + rlsize, rrsize := getChildrenSize(r) + if rlsize > rrsize { + avl.lrrotate(cur) + } else { + avl.lrotate(cur) + } + } +} + +func output(node *Node, prefix string, isTail bool, str *string) { + + if node.children[1] != nil { + newPrefix := prefix + if isTail { + newPrefix += "│ " + } else { + newPrefix += " " + } + output(node.children[1], newPrefix, false, str) + } + *str += prefix + if isTail { + *str += "└── " + } else { + *str += "┌── " + } + + *str += spew.Sprint(node.value) + "\n" + + if node.children[0] != nil { + newPrefix := prefix + if isTail { + newPrefix += " " + } else { + newPrefix += "│ " + } + output(node.children[0], newPrefix, true, str) + } + +} + +func outputfordebug(node *Node, prefix string, isTail bool, str *string) { + + if node.children[1] != nil { + newPrefix := prefix + if isTail { + newPrefix += "│ " + } else { + newPrefix += " " + } + outputfordebug(node.children[1], newPrefix, false, str) + } + *str += prefix + if isTail { + *str += "└── " + } else { + *str += "┌── " + } + + suffix := "(" + parentv := "" + if node.parent == nil { + parentv = "nil" + } else { + parentv = spew.Sprint(node.parent.value) + } + suffix += parentv + "|" + spew.Sprint(node.size) + ")" + *str += spew.Sprint(node.value) + suffix + "\n" + + if node.children[0] != nil { + newPrefix := prefix + if isTail { + newPrefix += " " + } else { + newPrefix += "│ " + } + outputfordebug(node.children[0], newPrefix, true, str) + } +} + +func (avl *Tree) debugString() string { + str := "AVLTree\n" + if avl.root == nil { + return str + "nil" + } + outputfordebug(avl.root, "", true, &str) + return str +} diff --git a/sbt/sbt_test.go b/sbt/sbt_test.go new file mode 100644 index 0000000..d856ca8 --- /dev/null +++ b/sbt/sbt_test.go @@ -0,0 +1,649 @@ +package avlindex + +import ( + "bytes" + "encoding/gob" + "io/ioutil" + "log" + "os" + "testing" + + "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" + "github.com/emirpasic/gods/utils" +) + +const CompartorSize = 1000000 +const NumberMax = 50000000 + +func TestSave(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) + } + + //fmt.Println(userBytes) + + 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) < CompartorSize; 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 TestIterator(t *testing.T) { + // avl := New(utils.IntComparator) + // for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 40, 50, 3, 40, 40, 40, 15} { + // avl.Put(v) + // } + // t.Error(avl.Values()) + // t.Error(avl.debugString()) + +} + +func TestIndexRange(t *testing.T) { + tree := New(utils.IntComparator) + 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) { + avl := New(utils.IntComparator) + for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} { + avl.Put(v) + } + + var Result string + + Result = spew.Sprint(avl.GetAround(3)) + if Result != "[7 3 ]" { + t.Error("avl.GetAround(3)) is error", Result) + } + + Result = spew.Sprint(avl.GetAround(40)) + if Result != "[40 40 30]" { + t.Error("avl.GetAround(40)) is error", Result) + } + + Result = spew.Sprint(avl.GetAround(50)) + if Result != "[ 50 40]" { + t.Error("avl.GetAround(50)) is error", Result) + } +} + +// // for test error case + +func TestPutComparatorRandom(t *testing.T) { + + for n := 0; n < 300000; n++ { + avl := New(utils.IntComparator) + 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) + "," + avl.Put(v) + godsavl.Put(v, v) + } + } + + s1 := spew.Sprint(avl.Values()) + s2 := spew.Sprint(godsavl.Values()) + + if s1 != s2 { + t.Error(godsavl.String()) + t.Error(avl.debugString()) + t.Error(content, n) + break + } + } +} + +func TestGet(t *testing.T) { + avl := New(utils.IntComparator) + for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + avl.Put(v) + } + + for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + v, ok := avl.Get(v) + if !ok { + t.Error("the val not found ", v) + } + } + + if v, ok := avl.Get(10000); ok { + t.Error("the val(1000) is not in tree, but is found", v) + } +} + +func TestTravalsal(t *testing.T) { + tree := New(utils.IntComparator) + + l := loadTestData() + N := len(l) + for i := 0; i < N; i++ { + tree.Put(l[i]) + } + + i := 0 + var result []interface{} + tree.Traversal(func(v interface{}) bool { + result = append(result, v) + i++ + if i >= 10 { + return false + } + return true + }) + t.Error(result) +} + +func TestRemoveAll(t *testing.T) { +ALL: + for c := 0; c < 5000; c++ { + avl := New(utils.IntComparator) + gods := avltree.NewWithIntComparator() + var l []int + m := make(map[int]int) + + for i := 0; len(l) < 10; i++ { + v := randomdata.Number(0, 100000) + if _, ok := m[v]; !ok { + m[v] = v + l = append(l, v) + avl.Put(v) + gods.Put(v, v) + } + } + + for i := 0; i < 10; i++ { + + avl.Remove(l[i]) + gods.Remove(l[i]) + + s1 := spew.Sprint(avl.Values()) + s2 := spew.Sprint(gods.Values()) + if s1 != s2 { + t.Error("avl remove error", "avlsize = ", avl.Size()) + t.Error(avl.root, i, l[i]) + t.Error(s1) + t.Error(s2) + break ALL + } + } + } +} + +func TestRemove(t *testing.T) { + +ALL: + for N := 0; N < 50000; N++ { + avl := New(utils.IntComparator) + gods := avltree.NewWithIntComparator() + + var l []int + m := make(map[int]int) + + for i := 0; len(l) < 10; i++ { + v := randomdata.Number(0, 100) + if _, ok := m[v]; !ok { + l = append(l, v) + m[v] = v + avl.Put(v) + gods.Put(v, v) + } + } + + src1 := avl.String() + src2 := gods.String() + + for i := 0; i < 10; i++ { + avl.Remove(l[i]) + gods.Remove(l[i]) + if avl.root != nil && spew.Sprint(gods.Values()) != spew.Sprint(avl.Values()) { + // if gods.String() != avl.String() && gods.Size() != 0 && avl.size != 0 { + t.Error(src1) + t.Error(src2) + t.Error(avl.debugString()) + t.Error(gods.String()) + t.Error(l[i]) + // t.Error(avl.TraversalDepth(-1)) + // t.Error(gods.Values()) + 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) { + tree := New(utils.IntComparator) + 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) { + sl := skiplist.New(skiplist.Int) + l := loadTestData() + + execCount := 50 + b.N = len(l) * execCount + + for i := 0; i < execCount; i++ { + for _, v := range l { + sl.Set(v, v) + } + } + +} + +func BenchmarkIterator(b *testing.B) { + tree := New(utils.IntComparator) + + 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 := New(utils.IntComparator) + + 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 := New(utils.IntComparator) + + l := loadTestData() + b.N = len(l) + for i := 0; i < b.N; i++ { + tree.Put(l[i]) + } + + b.ResetTimer() + b.StartTimer() + + execCount := 50 + 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 := 50 + 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 := 50 + 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 := 50 + b.N = len(l) * execCount + for i := 0; i < execCount; i++ { + avl := New(utils.IntComparator) + for _, v := range l { + avl.Put(v) + } + } +} + +func TestPutStable(t *testing.T) { + + // l := []int{14, 18, 20, 21, 22, 23, 19} + var l []int + for i := 0; len(l) < 10; i++ { + l = append(l, randomdata.Number(0, 65)) + } + + avl := New(utils.IntComparator) + for _, v := range l { + avl.Put(v) + t.Error(avl.debugString(), v) + } + t.Error(avl.Values()) + for _, v := range []int{10, 0, 9, 5, -11, -10, -1, -5} { + t.Error(avl.Index(v)) + } + + avl.RemoveIndex(4) + t.Error(avl.Index(4)) + t.Error(avl.Values()) + t.Error(avl.debugString()) + // t.Error(len(l), avl.debugString(), "\n", "-----------") // 3 6(4) + +} + +func BenchmarkIndex(b *testing.B) { + tree := New(utils.IntComparator) + + l := loadTestData() + b.N = len(l) + for i := 0; i < b.N; i++ { + tree.Put(l[i]) + } + + b.ResetTimer() + b.StartTimer() + + b.N = 1000000 + + var result [50]interface{} + for n := 0; n < b.N; n++ { + i := 0 + tree.Traversal(func(v interface{}) bool { + result[i] = v + i++ + if i < 50 { + return true + } + log.Print(i) + return false + }) + } +} + +func BenchmarkTraversal(b *testing.B) { + tree := New(utils.IntComparator) + + l := loadTestData() + b.N = len(l) + for i := 0; i < b.N; i++ { + tree.Put(l[i]) + } + + b.ResetTimer() + b.StartTimer() + + execCount := 50 + b.N = len(l) * execCount + + for n := 0; n < execCount; n++ { + i := 0 + var result []interface{} + tree.Traversal(func(v interface{}) bool { + result = append(result, v) + i++ + if i >= 50 { + return false + } + return true + }) + + } +} + +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) + } +}