From f0f16d751624ae9ab654867bef6948430f4812ce Mon Sep 17 00:00:00 2001 From: huangsimin Date: Tue, 2 Apr 2019 18:28:41 +0800 Subject: [PATCH] =?UTF-8?q?TODO:=20iter=20call=20=E5=A4=AA=E5=A4=9A?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=86=85=E5=AD=98.=20=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E6=95=88=E7=8E=87=E4=BD=8E=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- avl/avl.go | 52 ++++++++++++--------- avl/avl_test.go | 25 ++++++---- avl/iterator.go | 11 +++++ avldup/avldup.go | 41 ++++++++-------- avldup/avldup_test.go | 15 ++++-- avlkeydup/avlkeydup_test.go | 2 +- lastack/lastack.go | 12 ++++- lastack/lastack_test.go | 46 +++++++++--------- vbt/vbt.go | 93 ++++++++++++++++--------------------- vbt/vbt_test.go | 8 ++-- 10 files changed, 169 insertions(+), 136 deletions(-) diff --git a/avl/avl.go b/avl/avl.go index 5ab7cb2..0455b4c 100644 --- a/avl/avl.go +++ b/avl/avl.go @@ -28,10 +28,11 @@ type Tree struct { root *Node size int Compare compare.Compare + iter *Iterator } func New(Compare compare.Compare) *Tree { - return &Tree{Compare: Compare} + return &Tree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)} } func (tree *Tree) String() string { @@ -285,11 +286,12 @@ func (tree *Tree) GetNode(value interface{}) (*Node, bool) { case 1: n = n.children[1] case 0: - iter := NewIterator(n) - iter.Prev() - for iter.Prev() { - if tree.Compare(iter.cur.value, n.value) == 0 { - n = iter.cur + // iter := NewIterator(n) + tree.iter.SetNode(n) + tree.iter.Prev() + for tree.iter.Prev() { + if tree.Compare(tree.iter.cur.value, n.value) == 0 { + n = tree.iter.cur } else { break } @@ -310,25 +312,29 @@ func (tree *Tree) Put(value interface{}) { return } - cur := tree.root - parent := cur.parent - child := -1 - - for { - - if cur == nil { - parent.children[child] = node - node.parent = parent - if node.parent.height == 0 { - tree.fixPutHeight(node.parent) + for cur, c := tree.root, 0; ; { + c = tree.Compare(value, cur.value) + if c == -1 { + if cur.children[0] == nil { + cur.children[0] = node + node.parent = cur + if cur.height == 0 { + tree.fixPutHeight(cur) + } + return } - return + cur = cur.children[0] + } else { + if cur.children[1] == nil { + cur.children[1] = node + node.parent = cur + if cur.height == 0 { + tree.fixPutHeight(cur) + } + return + } + cur = cur.children[1] } - - parent = cur - c := tree.Compare(value, cur.value) - child = (c + 2) / 2 - cur = cur.children[child] } } diff --git a/avl/avl_test.go b/avl/avl_test.go index 38eb06a..c939111 100644 --- a/avl/avl_test.go +++ b/avl/avl_test.go @@ -247,11 +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} - tree := New(compare.Int) - for i := 0; i < 10; i++ { - tree.Put(randomdata.Number(0, 100)) - } - t.Error(tree.debugString()) + // 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", "-----------") } @@ -485,11 +485,20 @@ func BenchmarkGet(b *testing.B) { 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.Get(l[i]) + + execCount := 50 + b.N = len(l) * execCount + + for i := 0; i < execCount; i++ { + for _, v := range l { + tree.Get(v) + } } } @@ -526,7 +535,7 @@ func BenchmarkPut(b *testing.B) { b.ResetTimer() b.StartTimer() - execCount := 50 + execCount := 1000 b.N = len(l) * execCount for i := 0; i < execCount; i++ { tree := New(compare.Int) diff --git a/avl/iterator.go b/avl/iterator.go index 0db547f..f979838 100644 --- a/avl/iterator.go +++ b/avl/iterator.go @@ -24,6 +24,17 @@ func NewIterator(n *Node) *Iterator { return iter } +func NewIteratorWithCap(n *Node, cap int) *Iterator { + iter := &Iterator{tstack: lastack.NewWithCap(cap)} + iter.up = n + return iter +} + +func (iter *Iterator) SetNode(n *Node) { + iter.up = n + iter.tstack.Clear() +} + func (iter *Iterator) Value() interface{} { return iter.cur.value } diff --git a/avldup/avldup.go b/avldup/avldup.go index 5d8c686..8f811b1 100644 --- a/avldup/avldup.go +++ b/avldup/avldup.go @@ -292,29 +292,32 @@ func (tree *Tree) Put(value interface{}) { return } - cur := tree.root - parent := cur.parent - child := -1 - - for { - - if cur == nil { - parent.children[child] = node - node.parent = parent - if node.parent.height == 0 { - tree.fixPutHeight(node.parent) - } - return - } - - parent = cur - c := tree.Compare(value, cur.value) + for cur, c := tree.root, 0; ; { + c = tree.Compare(value, cur.value) if c == 0 { cur.value = value return + } else if c == -1 { + if cur.children[0] == nil { + cur.children[0] = node + node.parent = cur + if cur.height == 0 { + tree.fixPutHeight(cur) + } + return + } + cur = cur.children[0] + } else { + if cur.children[1] == nil { + cur.children[1] = node + node.parent = cur + if cur.height == 0 { + tree.fixPutHeight(cur) + } + return + } + cur = cur.children[1] } - child = (c + 2) / 2 - cur = cur.children[child] } } diff --git a/avldup/avldup_test.go b/avldup/avldup_test.go index abcaf17..0f883f6 100644 --- a/avldup/avldup_test.go +++ b/avldup/avldup_test.go @@ -397,11 +397,20 @@ func BenchmarkGet(b *testing.B) { 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.Get(l[i]) + + execCount := 500 + b.N = len(l) * execCount + b.Log(tree.size) + for i := 0; i < execCount; i++ { + for _, v := range l { + tree.Get(v) + } } } @@ -438,7 +447,7 @@ func BenchmarkPut(b *testing.B) { b.ResetTimer() b.StartTimer() - execCount := 50 + execCount := 1000 b.N = len(l) * execCount for i := 0; i < execCount; i++ { tree := New(compare.Int) diff --git a/avlkeydup/avlkeydup_test.go b/avlkeydup/avlkeydup_test.go index b76a5ab..544f889 100644 --- a/avlkeydup/avlkeydup_test.go +++ b/avlkeydup/avlkeydup_test.go @@ -438,7 +438,7 @@ func BenchmarkPut(b *testing.B) { b.ResetTimer() b.StartTimer() - execCount := 50 + execCount := 5 b.N = len(l) * execCount for i := 0; i < execCount; i++ { tree := New(compare.Int) diff --git a/lastack/lastack.go b/lastack/lastack.go index 196dc5a..6cc18c5 100644 --- a/lastack/lastack.go +++ b/lastack/lastack.go @@ -60,10 +60,18 @@ func New() *Stack { return s } +func NewWithCap(cap int) *Stack { + s := &Stack{} + s.size = 0 + s.top = &Node{elements: make([]interface{}, cap, cap), cur: -1} + return s +} + func (as *Stack) Clear() { as.size = 0 - as.top = &Node{elements: make([]interface{}, 8, 8), cur: -1} - as.cache = nil + + as.top.down = nil + as.top.cur = -1 } func (as *Stack) Empty() bool { diff --git a/lastack/lastack_test.go b/lastack/lastack_test.go index 8fedf9b..1281f1d 100644 --- a/lastack/lastack_test.go +++ b/lastack/lastack_test.go @@ -8,34 +8,34 @@ import ( "github.com/Pallinder/go-randomdata" ) -// func TestPush(t *testing.T) { -// s := New() -// for i := 0; i < 10; i++ { -// v := randomdata.Number(0, 10) -// s.Push(v) -// t.Error(v) -// t.Error(s.String(), " size ", s.size) -// } +func TestPush(t *testing.T) { + s := New() + for i := 0; i < 10; i++ { + v := randomdata.Number(0, 10) + s.Push(v) + t.Error(v) + t.Error(s.String(), " size ", s.size) + } -// t.Error(s.Values()) + t.Error(s.Values()) -// for i := 0; i < 10; i++ { -// v, ok := s.Pop() -// t.Error(v, ok) -// t.Error(s.String(), " size ", s.size) -// } + for i := 0; i < 10; i++ { + v, ok := s.Pop() + t.Error(v, ok) + t.Error(s.String(), " size ", s.size) + } -// for i := 0; i < 10; i++ { -// v := randomdata.Number(0, 10) -// s.Push(v) -// } + for i := 0; i < 10; i++ { + v := randomdata.Number(0, 10) + s.Push(v) + } -// for i := -1; i < 11; i++ { -// v, ok := s.Get(i) -// t.Error(v, ok) -// } + for i := -1; i < 11; i++ { + v, ok := s.Get(i) + t.Error(v, ok) + } -// } +} func BenchmarkGet(b *testing.B) { s := New() diff --git a/vbt/vbt.go b/vbt/vbt.go index 1f9e034..a9c554c 100644 --- a/vbt/vbt.go +++ b/vbt/vbt.go @@ -421,38 +421,48 @@ func (tree *Tree) Put(key interface{}) { return } - cur := tree.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) - tree.fix3Size(fixed, lefts, rigths) - } - return - } + for cur := tree.root; ; { 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 { - tree.fixSize(cur, ls, rs) + if cur.children[1].size >= cur.children[0].size*2+factor || cur.children[0].size >= cur.children[1].size*2+factor { + tree.fixSize(cur) } } cur.size++ - parent = cur c := tree.Compare(key, cur.value) - child = (c + 2) / 2 - cur = cur.children[child] + if c < 0 { + if cur.children[0] == nil { + cur.children[0] = node + node.parent = cur + + if cur.parent != nil && cur.parent.size == 3 { + if cur.parent.children[0] == nil { + tree.lrrotate3(cur.parent) + } else { + tree.rrotate3(cur.parent) + } + } + return + } + cur = cur.children[0] + } else { + if cur.children[1] == nil { + cur.children[1] = node + node.parent = cur + + if cur.parent != nil && cur.parent.size == 3 { + if cur.parent.children[1] == nil { + tree.rlrotate3(cur.parent) + } else { + tree.lrotate3(cur.parent) + } + } + return + } + cur = cur.children[1] + } } } @@ -850,48 +860,25 @@ func (tree *Tree) fixSizeWithRemove(cur *Node) { for cur != nil { cur.size-- if cur.size > 8 { - ls, rs := getChildrenSize(cur) factor := cur.size / 10 // or factor = 1 - if rs >= ls*2+factor || ls >= rs*2+factor { - tree.fixSize(cur, ls, rs) + if cur.children[1].size >= cur.children[0].size*2+factor || cur.children[0].size >= cur.children[1].size*2+factor { + tree.fixSize(cur) } } cur = cur.parent } } -func (tree *Tree) fix3Size(cur *Node, lefts, rigths int) { - if lefts > rigths { - l := cur.children[0] - llsize, lrsize := getChildrenSize(l) - if lrsize > llsize { - tree.rlrotate3(cur) - } else { - tree.rrotate3(cur) - } - } else { - r := cur.children[1] - rlsize, rrsize := getChildrenSize(r) - if rlsize > rrsize { - tree.lrrotate3(cur) - } else { - tree.lrotate3(cur) - } - } -} - -func (tree *Tree) fixSize(cur *Node, lefts, rigths int) { - if lefts > rigths { - l := cur.children[0] - llsize, lrsize := getChildrenSize(l) +func (tree *Tree) fixSize(cur *Node) { + if cur.children[0].size > cur.children[1].size { + llsize, lrsize := getChildrenSize(cur.children[0]) if lrsize > llsize { tree.rlrotate(cur) } else { tree.rrotate(cur) } } else { - r := cur.children[1] - rlsize, rrsize := getChildrenSize(r) + rlsize, rrsize := getChildrenSize(cur.children[1]) if rlsize > rrsize { tree.lrrotate(cur) } else { diff --git a/vbt/vbt_test.go b/vbt/vbt_test.go index 5cb6068..587f86b 100644 --- a/vbt/vbt_test.go +++ b/vbt/vbt_test.go @@ -17,10 +17,10 @@ import ( "github.com/emirpasic/gods/trees/redblacktree" ) -const CompareSize = 1000000 +const CompareSize = 5000 const NumberMax = 50000000 -func Save(t *testing.T) { +func TestSave(t *testing.T) { f, err := os.OpenFile("../l.log", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) if err != nil { @@ -552,7 +552,7 @@ func BenchmarkGet(b *testing.B) { b.ResetTimer() b.StartTimer() - execCount := 10 + execCount := 50 b.N = len(l) * execCount for i := 0; i < execCount; i++ { @@ -612,7 +612,7 @@ func BenchmarkPut(b *testing.B) { b.ResetTimer() b.StartTimer() - execCount := 10 + execCount := 1000 b.N = len(l) * execCount for i := 0; i < execCount; i++ { tree := New(compare.Int)