diff --git a/avlkey/avlkey.go b/avlkey/avlkey.go index c5a31bc..7911dc0 100644 --- a/avlkey/avlkey.go +++ b/avlkey/avlkey.go @@ -46,7 +46,7 @@ func (avl *Tree) String() string { if avl.size == 0 { return "" } - str := "AVLTree" + "\n" + str := "AVLTree\n" output(avl.root, "", true, &str) return str @@ -75,7 +75,7 @@ func (avl *Tree) Remove(key interface{}) *Node { if left == -1 && right == -1 { p := n.parent - p.children[n.child] = nil + p.children[getRelationship(n)] = nil avl.fixRemoveHeight(p) return n } @@ -88,7 +88,7 @@ func (avl *Tree) Remove(key interface{}) *Node { } cleft := cur.children[0] - cur.parent.children[cur.child] = cleft + cur.parent.children[getRelationship(cur)] = cleft if cleft != nil { cleft.parent = cur.parent } @@ -100,7 +100,7 @@ func (avl *Tree) Remove(key interface{}) *Node { } cright := cur.children[1] - cur.parent.children[cur.child] = cright + cur.parent.children[getRelationship(cur)] = cright if cright != nil { cright.parent = cur.parent @@ -108,10 +108,9 @@ func (avl *Tree) Remove(key interface{}) *Node { } cparent := cur.parent - // avl.replace(n, cur) 修改为interface - temp := n.value - n.value = cur.value - cur.value = temp + // 修改为interface 交换 + n.key, n.value, cur.key, cur.value = cur.key, cur.value, n.key, n.value + // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 if cparent == n { avl.fixRemoveHeight(n) @@ -125,8 +124,8 @@ func (avl *Tree) Remove(key interface{}) *Node { return nil } -func (avl *Tree) Get(v interface{}) (interface{}, bool) { - n, ok := avl.GetNode(v) +func (avl *Tree) Get(key interface{}) (interface{}, bool) { + n, ok := avl.GetNode(key) if ok { return n.value, true } @@ -136,7 +135,7 @@ func (avl *Tree) Get(v interface{}) (interface{}, bool) { func (avl *Tree) GetAround(key interface{}) (result [3]interface{}) { an := avl.GetAroundNode(key) for i, n := range an { - if n.value != nil { + if n != nil { result[i] = n.value } } @@ -198,8 +197,7 @@ func (avl *Tree) GetAroundNode(key interface{}) (result [3]*Node) { } func (avl *Tree) GetNode(key interface{}) (*Node, bool) { - n := avl.root - for n != nil { + for n := avl.root; n != nil; { switch c := avl.comparator(key, n.key); c { case -1: n = n.children[0] @@ -211,7 +209,6 @@ func (avl *Tree) GetNode(key interface{}) (*Node, bool) { panic("Get comparator only is allowed in -1, 0, 1") } } - return nil, false } @@ -256,6 +253,7 @@ func (avl *Tree) debugString() string { } func (avl *Tree) TraversalBreadth() (result []interface{}) { + result = make([]interface{}, 0, avl.size) var traverasl func(cur *Node) traverasl = func(cur *Node) { if cur == nil { @@ -270,7 +268,7 @@ func (avl *Tree) TraversalBreadth() (result []interface{}) { } func (avl *Tree) TraversalDepth(leftright int) (result []interface{}) { - + result = make([]interface{}, 0, avl.size) if leftright < 0 { var traverasl func(cur *Node) traverasl = func(cur *Node) { diff --git a/avlkey/avlkey_test.go b/avlkey/avlkey_test.go index d26f426..ed2c930 100644 --- a/avlkey/avlkey_test.go +++ b/avlkey/avlkey_test.go @@ -16,30 +16,46 @@ import ( "github.com/emirpasic/gods/utils" ) -// func TestRotate(t *testing.T) { -// avl := New(utils.IntComparator) +const CompartorSize = 500000 +const NumberMax = 60000000 -// content := "" -// for i := 0; i < 10; i++ { -// v := randomdata.Number(0, 1000) -// content += spew.Sprint(v) + " " -// avl.Put(v) -// } +func TestSave(t *testing.T) { -// t.Error(content) -// src := avl.String() -// t.Error(src) + f, err := os.OpenFile("../l.log", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) + if err != nil { + log.Println(err) + } -// lsrc := avl.String() -// t.Error(lsrc) -// // rrotate(&avl.root) -// rsrc := avl.String() -// t.Error(rsrc) + //fmt.Println(userBytes) -// if src == rsrc { -// t.Error("src == rsrc") -// } -// } + var l []int + 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) @@ -48,90 +64,89 @@ func TestIterator(t *testing.T) { avl.Put(v, v) } - t.Error(avl.TraversalDepth(1)) - t.Error(avl.debugString()) - iter := avl.Iterator() + // ` AVLTree + // │ ┌── 30 + // │ │ └── 21 + // │ ┌── 20 + // │ │ └── 15 + // └── 14 + // │ ┌── 7 + // │ ┌── 7 + // │ │ └── 6 + // └── 5 + // │ ┌── 4 + // │ │ └── 3 + // └── 2 + // └── 1` - for iter.Prev() { - t.Error(iter.Value()) - } - t.Error("prev == false", iter.Value(), iter.Prev(), iter.Value()) + iter := avl.Iterator() // root start point - for iter.Next() { - t.Error(iter.Value()) - } - t.Error("next == false", iter.Value(), iter.Next(), iter.Value()) + l := []int{14, 15, 20, 21, 30} - for iter.Prev() { - t.Error(iter.Value()) - } - t.Error("prev == false", iter.Value()) - - for i := 0; iter.Next(); i++ { - t.Error(iter.Value()) - if i >= 7 { - break + for i := 0; iter.Prev(); i++ { + if iter.Value().(int) != l[i] { + t.Error("iter prev error", iter.Value(), l[i]) } } - t.Error("next == false", iter.Value()) - for iter.Prev() { - t.Error(iter.Value()) + iter.Prev() + if iter.Value().(int) != 30 { + t.Error("prev == false", iter.Value(), iter.Prev(), iter.Value()) + } + + l = []int{21, 20, 15, 14, 7, 7, 6, 5, 4, 3, 2, 1} + for i := 0; iter.Next(); i++ { // cur is 30 next is 21 + if iter.Value().(int) != l[i] { + t.Error(iter.Value()) + } + } + + if iter.Next() != false { + t.Error("Next is error, cur is tail, val = 1 Next return false") + } + if iter.Value().(int) != 1 { // cur is 1 + t.Error("next == false", iter.Value(), iter.Next(), iter.Value()) + } + + if iter.Prev() != true && iter.Value().(int) != 2 { + t.Error("next to prev is error") } - t.Error("prev == false", iter.Value()) } -// func TestGetAround(t *testing.T) { -// avl := New(utils.IntComparator) -// for _, v := range []int{7, 14, 15, 20, 30, 21, 40, 40, 50, 3, 40, 40, 40} { -// t.Error(v) -// avl.Put(v) -// t.Error(avl.debugString()) -// } -// t.Error(avl.TraversalDepth(1)) -// t.Error(avl.GetAroundNode(40)) -// t.Error(avl.GetAround(40)) -// } - -func TestPutStable(t *testing.T) { +func TestGetAround(t *testing.T) { avl := New(utils.IntComparator) - gods := avltree.NewWithIntComparator() - // 44908, 34985, 62991, 4201, 27210, 30707 - for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { - t.Error(v) - t.Error(avl.debugString()) + for _, v := range []int{7, 14, 15, 20, 30, 21, 40, 40, 50, 3, 40, 40, 40} { avl.Put(v, v) - gods.Put(v, v) - t.Error(avl.debugString()) - t.Error(gods.String()) } - // avl = New(utils.IntComparator) - // for _, v := range []int{88, 77, 80} { - // avl.Put(v) - // t.Error(avl.String()) + + if spew.Sprint(avl.GetAround(30)) != "[40 30 21]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(30))) + } + + if spew.Sprint(avl.GetAround(40)) != "[40 40 30]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(50))) + } + + if spew.Sprint(avl.GetAround(50)) != "[ 50 40]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(50))) + } +} + +// for test error case +func TestPutStable(t *testing.T) { + // avl := New(utils.IntComparator) + // gods := avltree.NewWithIntComparator() + // // 44908, 34985, 62991, 4201, 27210, 30707 + // for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + // t.Error(v) + // t.Error(avl.debugString()) + // avl.Put(v, v) + // gods.Put(v, v) + // t.Error(avl.debugString()) + // t.Error(gods.String()) // } } -// func TestDiffPutRandom(t *testing.T) { -// avl := New(utils.IntComparator) -// godsavl := avltree.NewWithIntComparator() - -// content := "" -// m := make(map[int]int) -// for i := 0; len(m) < 10; i++ { -// v := randomdata.Number(0, 10000) -// if _, ok := m[v]; !ok { -// m[v] = v -// content += spew.Sprint(v) + " " -// t.Error(v) -// avl.Put(v) -// t.Error(avl.String()) -// godsavl.Put(v, v) -// } -// } -// t.Error(godsavl.String()) -// } - func TestPutComparatorRandom(t *testing.T) { for n := 0; n < 300000; n++ { @@ -159,346 +174,262 @@ func TestPutComparatorRandom(t *testing.T) { break } } - - // t.Error(content) - // t.Error(avl.String()) - // t.Error(godsavl.String()) - // t.Error(avl.String() == godsavl.String()) - } -// func TestGet(t *testing.T) { -// avl := New(utils.IntComparator) -// for i := 0; i < 15; i++ { -// avl.Put(randomdata.Number(0, 1000)) -// } const l = 1 -// const r = 0 - -// t.Error(avl.String()) -// t.Error(avl.Get(500)) -// } - -// func TestRemoveAll(t *testing.T) { - -// for c := 0; c < 10000; c++ { -// // f, _ := os.OpenFile("./out.log", os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0666) -// // log.SetOutput(f) - -// avl := New(utils.IntComparator) -// var l []int -// for i := 0; i < 100; i++ { -// v := randomdata.Number(0, 100000) -// l = append(l, v) -// avl.Put(v) -// } -// // defer func() { -// // if err := recover(); err != nil { -// // panic(avl.String()) -// // } -// // }() -// // log.Println(avl.TraversalBreadth()) -// for i := 0; i < 100; i++ { -// // log.Println(l[i]) -// // log.Println(avl.debugString()) -// avl.Remove(l[i]) -// } -// } -// } - -// func TestRemove(t *testing.T) { - -// // avl := New(utils.IntComparator) - -// // var l []int -// // for _, v := range []int{86, 97, 9, 61, 37, 45, 97, 43, 95, 8} { -// // l = append(l, v) -// // avl.Put(v) -// // } - -// // for i := 0; i < len(l); i++ { -// // // log.Println(i) -// // log.Println("begin", l[i], avl.debugString()) -// // avl.Remove(l[i]) -// // log.Println("end", l[i], avl.debugString()) -// // } - -// ALL: -// for N := 0; N < 500000; 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 spew.Sprint(gods.Values()) != spew.Sprint(avl.TraversalDepth(-1)) && avl.size != 0 { -// // 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 - -// } -// } -// } -// } - -const CompartorSize = 500000 -const NumberMax = 60000000 - -// func BenchmarkIterator(b *testing.B) { -// avl := New(utils.IntComparator) -// b.N = CompartorSize - -// for i := 0; i < b.N; i++ { -// v := randomdata.Number(0, NumberMax) -// avl.Put(v) -// } - -// b.ResetTimer() -// b.StartTimer() -// iter := avl.Iterator() -// for iter.Next() { - -// } - -// for iter.Prev() { - -// } - -// for iter.Next() { - -// } - -// } - -// func BenchmarkGodsIterator(b *testing.B) { -// avl := avltree.NewWithIntComparator() -// b.N = CompartorSize - -// for i := 0; i < b.N; i++ { -// v := randomdata.Number(0, NumberMax) -// avl.Put(v, i) -// } - -// b.ResetTimer() -// b.StartTimer() -// iter := avl.Iterator() -// for iter.Next() { - -// } - -// for iter.Prev() { - -// } - -// for iter.Next() { - -// } - -// } - -// func BenchmarkRemove(b *testing.B) { - -// avl := New(utils.IntComparator) -// b.N = CompartorSize - -// var l []int -// for i := 0; i < b.N; i++ { -// v := randomdata.Number(0, NumberMax) -// l = append(l, v) -// avl.Put(v) -// } - -// b.ResetTimer() -// b.StartTimer() - -// for i := 0; i < b.N; i++ { -// avl.Remove(l[i]) -// } -// } - -// func BenchmarkGodsRemove(b *testing.B) { -// avl := avltree.NewWithIntComparator() -// b.N = CompartorSize - -// var l []int -// for i := 0; i < b.N; i++ { -// v := randomdata.Number(0, NumberMax) -// l = append(l, v) -// avl.Put(v, v) -// } - -// b.ResetTimer() -// b.StartTimer() - -// for i := 0; i < b.N; i++ { -// avl.Remove(l[i]) -// } -// } - -// func BenchmarkGoGet(b *testing.B) { -// avl := make(map[int]int) - -// b.N = CompartorSize -// for i := 0; i < b.N; i++ { -// avl[randomdata.Number(0, NumberMax)] = i -// } - -// b.ResetTimer() -// b.StartTimer() -// b.N = CompartorSize - -// var v int -// var ok bool -// for i := 0; i < b.N; i++ { -// v, ok = avl[randomdata.Number(0, NumberMax)] -// } - -// if ok && v == 1 { -// v = 1 -// } -// } - -// func BenchmarkGet(b *testing.B) { - -// avl := New(utils.IntComparator) - -// b.N = CompartorSize -// for i := 0; i < b.N/2; i++ { -// avl.Put(randomdata.Number(0, NumberMax)) -// } - -// b.ResetTimer() -// b.StartTimer() -// for i := 0; i < b.N; i++ { -// avl.Get(randomdata.Number(0, NumberMax)) -// } -// } - -// func BenchmarkGodsRBGet(b *testing.B) { -// rb := redblacktree.NewWithIntComparator() - -// b.N = CompartorSize -// for i := 0; i < b.N/2; i++ { -// rb.Put(randomdata.Number(0, NumberMax), i) -// } - -// b.ResetTimer() -// b.StartTimer() -// for i := 0; i < b.N; i++ { -// rb.Get(randomdata.Number(0, NumberMax)) -// } -// } - -// func BenchmarkGodsAvlGet(b *testing.B) { -// rb := avltree.NewWithIntComparator() - -// b.N = CompartorSize -// for i := 0; i < b.N/2; i++ { -// rb.Put(randomdata.Number(0, NumberMax), i) -// } - -// b.ResetTimer() -// b.StartTimer() -// for i := 0; i < b.N; i++ { -// rb.Get(randomdata.Number(0, NumberMax)) -// } -// } - -// func BenchmarkGoPut(b *testing.B) { -// avl := make(map[int]int) - -// for i := 0; i < 100000; i++ { -// avl[randomdata.Number(0, NumberMax)] = i -// } - -// b.ResetTimer() -// b.StartTimer() -// b.N = CompartorSize - -// for i := 0; i < b.N; i++ { -// avl[randomdata.Number(0, NumberMax)] = i -// } - -// log.Println(avl[12]) -// } - -// func BenchmarkGodsHashmap(b *testing.B) { -// avl := hashmap.New() - -// b.N = CompartorSize * 10 -// for i := 0; i < b.N; i++ { -// avl.Put(randomdata.Number(0, NumberMax), i) -// } - -// // b.ResetTimer() -// // b.StartTimer() -// // b.N = CompartorSize - -// // for i := 0; i < b.N; i++ { -// // avl[randomdata.Number(0, NumberMax)] = i -// // } -// } - -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) +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, v) } - //fmt.Println(userBytes) + result := ` +│ ┌── 57092 +│ ┌── 39016 +│ │ └── 36513 +│ ┌── 27897 +│ │ │ ┌── 23202 +│ │ └── 22574 +└── 7666 + │ ┌── 3055 + └── 2383 + └── 1562 +` - var l []int - 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) + s1 := avl.String() + s2 := "AVLTree" + result + if s1 != s2 { + t.Error(s1, s2) + } + + 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) } } - var result bytes.Buffer - encoder := gob.NewEncoder(&result) - encoder.Encode(l) - lbytes := result.Bytes() - f.Write(lbytes) + if v, ok := avl.Get(10000); ok { + t.Error("the val(1000) is not in tree, but is found", v) + } } +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) < 100; i++ { + v := randomdata.Number(0, 100000) + if _, ok := m[v]; !ok { + m[v] = v + l = append(l, v) + avl.Put(v, v) + gods.Put(v, v) + } + } + + for i := 0; i < 100; i++ { + avl.Remove(l[i]) + gods.Remove(l[i]) + s1 := spew.Sprint(avl.TraversalDepth(-1)) + s2 := spew.Sprint(gods.Values()) + if s1 != s2 { + t.Error("avl remove error", "avlsize = ", avl.Size()) + t.Error(s1) + t.Error(s2) + break ALL + } + } + } +} + +func TestRemove(t *testing.T) { + +ALL: + for N := 0; N < 500000; 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, 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 spew.Sprint(gods.Values()) != spew.Sprint(avl.TraversalDepth(-1)) && avl.size != 0 { + // 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 BenchmarkIterator(b *testing.B) { + tree := New(utils.IntComparator) + + l := loadTestData() + b.N = len(l) + + for _, v := range l { + tree.Put(v, v) + } + + b.ResetTimer() + b.StartTimer() + iter := tree.Iterator() + for iter.Next() { + } + for iter.Prev() { + } + for iter.Next() { + } + +} + +func BenchmarkGodsIterator(b *testing.B) { + tree := avltree.NewWithIntComparator() + + l := loadTestData() + b.N = len(l) + + for _, v := range l { + tree.Put(v, v) + } + + b.ResetTimer() + b.StartTimer() + iter := tree.Iterator() + for iter.Next() { + } + for iter.Prev() { + } + for iter.Next() { + } +} + +func BenchmarkRemove(b *testing.B) { + tree := New(utils.IntComparator) + + 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 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) { + + avl := New(utils.IntComparator) + + l := loadTestData() + b.N = len(l) + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + avl.Get(l[i]) + } +} + +func BenchmarkGodsRBGet(b *testing.B) { + tree := redblacktree.NewWithIntComparator() + + l := loadTestData() + b.N = len(l) + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + tree.Get(l[i]) + } +} + +func BenchmarkGodsAvlGet(b *testing.B) { + tree := avltree.NewWithIntComparator() + + l := loadTestData() + b.N = len(l) + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + tree.Get(l[i]) + } +} + func BenchmarkPut(b *testing.B) { avl := New(utils.IntComparator) - data, err := ioutil.ReadFile("./l.log") - if err != nil { - b.Error(err) - } - - var l []int - - decoder := gob.NewDecoder(bytes.NewReader(data)) - decoder.Decode(&l) + l := loadTestData() b.ResetTimer() b.StartTimer() @@ -513,15 +444,7 @@ func BenchmarkPut(b *testing.B) { func BenchmarkGodsRBPut(b *testing.B) { tree := redblacktree.NewWithIntComparator() - data, err := ioutil.ReadFile("./l.log") - if err != nil { - b.Error(err) - } - - var l []int - - decoder := gob.NewDecoder(bytes.NewReader(data)) - decoder.Decode(&l) + l := loadTestData() b.ResetTimer() b.StartTimer() @@ -535,15 +458,7 @@ func BenchmarkGodsRBPut(b *testing.B) { func BenchmarkGodsPut(b *testing.B) { tree := avltree.NewWithIntComparator() - data, err := ioutil.ReadFile("./l.log") - if err != nil { - b.Error(err) - } - - var l []int - - decoder := gob.NewDecoder(bytes.NewReader(data)) - decoder.Decode(&l) + l := loadTestData() b.ResetTimer() b.StartTimer() diff --git a/avlkeydup/avlkeydup.go b/avlkeydup/avlkeydup.go new file mode 100644 index 0000000..1f43ff9 --- /dev/null +++ b/avlkeydup/avlkeydup.go @@ -0,0 +1,650 @@ +package avl + +import ( + "github.com/davecgh/go-spew/spew" + + "github.com/emirpasic/gods/utils" +) + +type Node struct { + children [2]*Node + parent *Node + height int + key, value interface{} +} + +// func (n *Node) String() string { +// if n == nil { +// return "nil" +// } +// return spew.Sprint(n.value) +// } + +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.height) + ")" +} + +type Tree struct { + root *Node + size int + comparator utils.Comparator +} + +func New(comparator utils.Comparator) *Tree { + return &Tree{comparator: comparator} +} + +func (avl *Tree) String() string { + if avl.size == 0 { + return "" + } + str := "AVLTree\n" + output(avl.root, "", true, &str) + + return str +} + +func (avl *Tree) Iterator() *Iterator { + return initIterator(avl) +} + +func (avl *Tree) Size() int { + return avl.size +} + +func (avl *Tree) Remove(key interface{}) *Node { + + if n, ok := avl.GetNode(key); ok { + + avl.size-- + if avl.size == 0 { + avl.root = nil + return n + } + + left := getHeight(n.children[0]) + right := getHeight(n.children[1]) + + if left == -1 && right == -1 { + p := n.parent + p.children[getRelationship(n)] = nil + avl.fixRemoveHeight(p) + return n + } + + var cur *Node + if left > right { + 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.key, n.value, cur.key, cur.value = cur.key, cur.value, n.key, n.value + + // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 + if cparent == n { + avl.fixRemoveHeight(n) + } else { + avl.fixRemoveHeight(cparent) + } + + return cur + } + + return nil +} + +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(key interface{}) (result [3]*Node) { + n := avl.root + + for { + + if n == nil { + return + } + + lastc := 0 + switch c := avl.comparator(key, n.key); c { + case -1: + if c != -lastc { + result[0] = n + } + lastc = c + n = n.children[0] + case 1: + if c != -lastc { + result[2] = n + } + lastc = c + n = n.children[1] + case 0: + + switch lastc { + case -1: + if n.children[1] != nil { + result[0] = n.children[1] + } + case 1: + if n.children[0] != nil { + result[2] = n.children[0] + } + case 0: + + if n.children[1] != nil { + result[0] = n.children[1] + } + if n.children[0] != nil { + result[2] = n.children[0] + } + + result[1] = n + return + } + + default: + panic("Get comparator only is allowed in -1, 0, 1") + } + + } +} +func (avl *Tree) GetNode(key interface{}) (*Node, bool) { + + for n := avl.root; n != nil; { + switch c := avl.comparator(key, n.key); 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(key, value interface{}) { + + if avl.size == 0 { + avl.root = &Node{key: key, value: value} + avl.size++ + return + } + + cur := avl.root + parent := cur.parent + child := -1 + + for { + + if cur == nil { + avl.size++ + node := &Node{key: key, value: value} + parent.children[child] = node + node.parent = parent + if node.parent.height == 0 { + avl.fixPutHeight(node.parent) + } + return + } + + parent = cur + c := avl.comparator(key, cur.key) + + if c == 0 { + cur.key = key + cur.value = value + return + } + + child = (c + 2) / 2 + cur = cur.children[child] + } + +} + +func (avl *Tree) debugString() string { + if avl.size == 0 { + return "" + } + str := "AVLTree\n" + outputfordebug(avl.root, "", true, &str) + return str +} + +func (avl *Tree) TraversalBreadth() (result []interface{}) { + result = make([]interface{}, 0, avl.size) + var traverasl func(cur *Node) + traverasl = func(cur *Node) { + if cur == nil { + return + } + result = append(result, cur.value) + traverasl(cur.children[0]) + traverasl(cur.children[1]) + } + traverasl(avl.root) + return +} + +func (avl *Tree) TraversalDepth(leftright int) (result []interface{}) { + result = make([]interface{}, 0, avl.size) + if leftright < 0 { + var traverasl func(cur *Node) + traverasl = func(cur *Node) { + if cur == nil { + return + } + traverasl(cur.children[0]) + result = append(result, cur.value) + traverasl(cur.children[1]) + } + traverasl(avl.root) + } else { + var traverasl func(cur *Node) + traverasl = func(cur *Node) { + if cur == nil { + return + } + traverasl(cur.children[1]) + result = append(result, cur.value) + traverasl(cur.children[0]) + } + traverasl(avl.root) + } + + return +} + +func (avl *Tree) lrrotate(cur *Node) { + + const l = 1 + const r = 0 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, 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 + + mov.height = getMaxChildrenHeight(mov) + 1 + movparent.height = getMaxChildrenHeight(movparent) + 1 + cur.height = getMaxChildrenHeight(cur) + 1 +} + +func (avl *Tree) rlrotate(cur *Node) { + + const l = 0 + const r = 1 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, 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 + + mov.height = getMaxChildrenHeight(mov) + 1 + movparent.height = getMaxChildrenHeight(movparent) + 1 + cur.height = getMaxChildrenHeight(cur) + 1 +} + +func (avl *Tree) rrotate(cur *Node) { + + const l = 0 + const r = 1 + // 1 right 0 left + mov := cur.children[l] + + mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, mov.value //交换值达到, 相对位移 + + // if mov.children[l] != nil { + // mov.children[l].parent = cur + // cur.children[l] = mov.children[l] + // } else { + // cur.children[l] = nil + // } + + // 不可能为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 + + mov.height = getMaxChildrenHeight(mov) + 1 + cur.height = getMaxChildrenHeight(cur) + 1 +} + +func (avl *Tree) lrotate(cur *Node) { + + const l = 1 + const r = 0 + + mov := cur.children[l] + + mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, mov.value //交换值达到, 相对位移 + + // if mov.children[l] != nil { + // mov.children[l].parent = cur + // cur.children[l] = mov.children[l] + // } else { + // cur.children[l] = nil + // } + + // 不可能为nil + mov.children[l].parent = cur + cur.children[l] = mov.children[l] + + 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.height = getMaxChildrenHeight(mov) + 1 + cur.height = getMaxChildrenHeight(cur) + 1 +} + +func getMaxAndChildrenHeight(cur *Node) (h1, h2, maxh int) { + h1 = getHeight(cur.children[0]) + h2 = getHeight(cur.children[1]) + if h1 > h2 { + maxh = h1 + } else { + maxh = h2 + } + + return +} + +func getMaxChildrenHeight(cur *Node) int { + h1 := getHeight(cur.children[0]) + h2 := getHeight(cur.children[1]) + if h1 > h2 { + return h1 + } + return h2 +} + +func getHeight(cur *Node) int { + if cur == nil { + return -1 + } + return cur.height +} + +func (avl *Tree) fixRemoveHeight(cur *Node) { + + for { + + lefth, rigthh, lrmax := getMaxAndChildrenHeight(cur) + + // 判断当前节点是否有变化, 如果没变化的时候, 不需要往上修复 + isBreak := false + if cur.height == lrmax+1 { + isBreak = true + } else { + cur.height = lrmax + 1 + } + + // 计算高度的差值 绝对值大于2的时候需要旋转 + diff := lefth - rigthh + if diff < -1 { + r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 + if getHeight(r.children[0]) > getHeight(r.children[1]) { + avl.lrrotate(cur) + } else { + avl.lrotate(cur) + } + } else if diff > 1 { + l := cur.children[0] + if getHeight(l.children[1]) > getHeight(l.children[0]) { + avl.rlrotate(cur) + } else { + avl.rrotate(cur) + } + } else { + + if isBreak { + return + } + + } + + if cur.parent == nil { + return + } + + cur = cur.parent + } + +} + +func (avl *Tree) fixPutHeight(cur *Node) { + + for { + + lefth := getHeight(cur.children[0]) + rigthh := getHeight(cur.children[1]) + + // 计算高度的差值 绝对值大于2的时候需要旋转 + diff := lefth - rigthh + if diff < -1 { + r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 + if getHeight(r.children[0]) > getHeight(r.children[1]) { + avl.lrrotate(cur) + } else { + avl.lrotate(cur) + } + } else if diff > 1 { + l := cur.children[0] + if getHeight(l.children[1]) > getHeight(l.children[0]) { + avl.rlrotate(cur) + } else { + avl.rrotate(cur) + } + + } else { + // 选择一个child的最大高度 + 1为 高度 + if lefth > rigthh { + cur.height = lefth + 1 + } else { + cur.height = rigthh + 1 + } + } + + if cur.parent == nil || cur.height < cur.parent.height { + return + } + cur = cur.parent + } +} + +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.height) + ")" + *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) + } +} diff --git a/avlkeydup/avlkeydup_test.go b/avlkeydup/avlkeydup_test.go new file mode 100644 index 0000000..22c940a --- /dev/null +++ b/avlkeydup/avlkeydup_test.go @@ -0,0 +1,495 @@ +package avl + +import ( + "bytes" + "encoding/gob" + "io/ioutil" + "log" + "os" + "testing" + + "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 = 500000 +const NumberMax = 60000000 + +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 + 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 TestDupKey(t *testing.T) { + tree1 := New(utils.IntComparator) + tree2 := avltree.NewWithIntComparator() + + for i := 0; i < CompartorSize/100; i++ { + v := randomdata.Number(0, NumberMax) + tree1.Put(v, v) + tree2.Put(v, v) + } + + tree1.Put(500, 500) + tree2.Put(500, 500) + + tree1.Put(500, 500) + tree2.Put(500, 500) + + if tree1.Size() != tree2.Size() { + t.Error("tree size is not equal") + } + + if tree1.String() != tree2.String() { + t.Error(tree1.String()) + } +} + +func TestIterator(t *testing.T) { + avl := New(utils.IntComparator) + for _, v := range []int{1, 2, 7, 4, 5, 6, 7, 14, 15, 20, 30, 21, 3} { + // t.Error(v) + avl.Put(v, v) + + } + // ` AVLTree + // │ ┌── 30 + // │ │ └── 21 + // │ ┌── 20 + // │ │ └── 15 + // └── 14 + // │ ┌── 7 + // │ ┌── 7 + // │ │ └── 6 + // └── 5 + // │ ┌── 4 + // │ │ └── 3 + // └── 2 + // └── 1` + + iter := avl.Iterator() // root start point + + l := []int{14, 15, 20, 21, 30} + + for i := 0; iter.Prev(); i++ { + if iter.Value().(int) != l[i] { + t.Error("iter prev error", iter.Value(), l[i]) + } + } + + iter.Prev() + if iter.Value().(int) != 30 { + t.Error("prev == false", iter.Value(), iter.Prev(), iter.Value()) + } + + l = []int{21, 20, 15, 14, 7, 7, 6, 5, 4, 3, 2, 1} + for i := 0; iter.Next(); i++ { // cur is 30 next is 21 + if iter.Value().(int) != l[i] { + t.Error(iter.Value()) + } + } + + if iter.Next() != false { + t.Error("Next is error, cur is tail, val = 1 Next return false") + } + if iter.Value().(int) != 1 { // cur is 1 + t.Error("next == false", iter.Value(), iter.Next(), iter.Value()) + } + + if iter.Prev() != true && iter.Value().(int) != 2 { + t.Error("next to prev is error") + } +} + +func TestGetAround(t *testing.T) { + avl := New(utils.IntComparator) + for _, v := range []int{7, 14, 15, 20, 30, 21, 40, 40, 50, 3, 40, 40, 40} { + avl.Put(v, v) + } + + if spew.Sprint(avl.GetAround(30)) != "[40 30 21]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(30))) + } + + if spew.Sprint(avl.GetAround(40)) != "[40 40 30]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(50))) + } + + if spew.Sprint(avl.GetAround(50)) != "[ 50 40]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(50))) + } +} + +// for test error case +func TestPutStable(t *testing.T) { + // avl := New(utils.IntComparator) + // gods := avltree.NewWithIntComparator() + // // 44908, 34985, 62991, 4201, 27210, 30707 + // for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + // t.Error(v) + // t.Error(avl.debugString()) + // avl.Put(v, v) + // gods.Put(v, v) + // t.Error(avl.debugString()) + // t.Error(gods.String()) + // } +} + +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) + "," + // t.Error(v) + avl.Put(v, v) + // t.Error(avl.String()) + godsavl.Put(v, v) + } + } + + if avl.String() != godsavl.String() { + 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, v) + } + + result := ` +│ ┌── 57092 +│ ┌── 39016 +│ │ └── 36513 +│ ┌── 27897 +│ │ │ ┌── 23202 +│ │ └── 22574 +└── 7666 + │ ┌── 3055 + └── 2383 + └── 1562 +` + + s1 := avl.String() + s2 := "AVLTree" + result + if s1 != s2 { + t.Error(s1, s2) + } + + 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 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) < 100; i++ { + v := randomdata.Number(0, 100000) + if _, ok := m[v]; !ok { + m[v] = v + l = append(l, v) + avl.Put(v, v) + gods.Put(v, v) + } + } + + for i := 0; i < 100; i++ { + avl.Remove(l[i]) + gods.Remove(l[i]) + s1 := spew.Sprint(avl.TraversalDepth(-1)) + s2 := spew.Sprint(gods.Values()) + if s1 != s2 { + t.Error("avl remove error", "avlsize = ", avl.Size()) + t.Error(s1) + t.Error(s2) + break ALL + } + } + } +} + +func TestRemove(t *testing.T) { + +ALL: + for N := 0; N < 500000; 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, 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 spew.Sprint(gods.Values()) != spew.Sprint(avl.TraversalDepth(-1)) && avl.size != 0 { + // 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 BenchmarkIterator(b *testing.B) { + tree := New(utils.IntComparator) + + l := loadTestData() + b.N = len(l) + + for _, v := range l { + tree.Put(v, v) + } + + b.ResetTimer() + b.StartTimer() + iter := tree.Iterator() + for iter.Next() { + } + for iter.Prev() { + } + for iter.Next() { + } + +} + +func BenchmarkGodsIterator(b *testing.B) { + tree := avltree.NewWithIntComparator() + + l := loadTestData() + b.N = len(l) + + for _, v := range l { + tree.Put(v, v) + } + + b.ResetTimer() + b.StartTimer() + iter := tree.Iterator() + for iter.Next() { + } + for iter.Prev() { + } + for iter.Next() { + } +} + +func BenchmarkRemove(b *testing.B) { + tree := New(utils.IntComparator) + + 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 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) { + + avl := New(utils.IntComparator) + + l := loadTestData() + b.N = len(l) + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + avl.Get(l[i]) + } +} + +func BenchmarkGodsRBGet(b *testing.B) { + tree := redblacktree.NewWithIntComparator() + + l := loadTestData() + b.N = len(l) + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + tree.Get(l[i]) + } +} + +func BenchmarkGodsAvlGet(b *testing.B) { + tree := avltree.NewWithIntComparator() + + l := loadTestData() + b.N = len(l) + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + tree.Get(l[i]) + } +} + +func BenchmarkPut(b *testing.B) { + avl := New(utils.IntComparator) + + l := loadTestData() + + b.ResetTimer() + b.StartTimer() + + b.N = len(l) + for _, v := range l { + avl.Put(v, v) + } + +} + +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) + } +} diff --git a/avlkeydup/iterator.go b/avlkeydup/iterator.go new file mode 100644 index 0000000..3ca4567 --- /dev/null +++ b/avlkeydup/iterator.go @@ -0,0 +1,152 @@ +package avl + +import ( + "474420502.top/eson/structure/lastack" +) + +type Iterator struct { + op *Tree + + dir int + up *Node + cur *Node + tstack *lastack.Stack + // curnext *Node +} + +func initIterator(avltree *Tree) *Iterator { + iter := &Iterator{op: avltree, tstack: lastack.New()} + iter.up = avltree.root + 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 (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 (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) + } + } +}