diff --git a/avl/avl_test.go b/avl/avl_test.go index d5b6a52..86da345 100644 --- a/avl/avl_test.go +++ b/avl/avl_test.go @@ -324,13 +324,13 @@ func TestGet(t *testing.T) { func TestRemoveAll(t *testing.T) { ALL: - for c := 0; c < 5000; c++ { + for c := 0; c < 50000; c++ { tree := New(compare.Int) gods := avltree.NewWithIntComparator() var l []int m := make(map[int]int) - for i := 0; len(l) < 100; i++ { + for i := 0; len(l) < 50; i++ { v := randomdata.Number(0, 100000) if _, ok := m[v]; !ok { m[v] = v @@ -340,7 +340,7 @@ ALL: } } - for i := 0; i < 100; i++ { + for i := 0; i < 50; i++ { tree.Remove(l[i]) gods.Remove(l[i]) s1 := spew.Sprint(tree.Values()) diff --git a/priority_queue/priority_queue.go b/priority_queue/priority_queue.go index 90136e9..ad2f87f 100644 --- a/priority_queue/priority_queue.go +++ b/priority_queue/priority_queue.go @@ -6,7 +6,6 @@ import ( type PriorityQueue struct { queue *vbTree - head *tNode } func (pq *PriorityQueue) Iterator() *Iterator { @@ -22,33 +21,41 @@ func (pq *PriorityQueue) Size() int { } func (pq *PriorityQueue) Push(value interface{}) { - + pq.queue.Put(value) } func (pq *PriorityQueue) Top() (result interface{}, ok bool) { - if pq.head != nil { - return pq.head.value, true + if pq.queue.top != nil { + return pq.queue.top.value, true } return nil, false } func (pq *PriorityQueue) Pop() (result interface{}, ok bool) { - + if pq.queue.top != nil { + result = pq.queue.top.value + pq.queue.removeNode(pq.queue.top) + return result, true + } return nil, false } -func (pq *PriorityQueue) Get(idx int) (interface{}, bool) { - return nil, false +func (pq *PriorityQueue) Index(idx int) (interface{}, bool) { + return pq.queue.Index(idx) } -func (pq *PriorityQueue) RemoveWithIndex(idx int) { - +func (pq *PriorityQueue) Get(key interface{}) (interface{}, bool) { + return pq.queue.Get(key) } -func (pq *PriorityQueue) Remove(key interface{}) { +func (pq *PriorityQueue) RemoveWithIndex(idx int) bool { + return pq.queue.RemoveIndex(idx) +} +func (pq *PriorityQueue) Remove(key interface{}) bool { + return pq.queue.Remove(key) } func (pq *PriorityQueue) Values() []interface{} { - return nil + return pq.queue.Values() } diff --git a/priority_queue/priority_queue_test.go b/priority_queue/priority_queue_test.go index c65521c..036617b 100644 --- a/priority_queue/priority_queue_test.go +++ b/priority_queue/priority_queue_test.go @@ -3,35 +3,178 @@ package pqueue import ( "testing" - "github.com/Pallinder/go-randomdata" - "474420502.top/eson/structure/compare" ) -func TestPush(t *testing.T) { +func TestQueuePush(t *testing.T) { pq := New(compare.Int) - for i := 0; i < 10; i++ { - v := randomdata.Number(0, 100) + for _, v := range []int{32, 10, 53, 78, 90, 1, 4} { pq.Push(v) + if v, ok := pq.Top(); ok { + } else { + t.Error(v) + } + } + + if v, ok := pq.Top(); ok { + if v != 90 { + t.Error(v) + } + } else { t.Error(v) } - t.Error(pq.Pop()) - t.Error(pq.Pop()) - t.Error(pq.Pop()) - t.Error(pq.Pop()) - t.Error(pq.Pop()) + } -func TestPop(t *testing.T) { +func TestQueuePop(t *testing.T) { pq := New(compare.Int) - for i := 0; i < 10; i++ { - v := randomdata.Number(0, 100) + for _, v := range []int{32, 10, 53, 78, 90, 1, 4} { pq.Push(v) + if v, ok := pq.Top(); ok { + } else { + t.Error(v) + } + } + + l := []int{90, 78, 53, 32, 10, 4, 1} + for _, lv := range l { + if v, ok := pq.Pop(); ok { + if v != lv { + t.Error(v) + } + } else { + t.Error(v) + } + } + + if v, ok := pq.Pop(); ok { + t.Error(v) + } +} + +func TestQueueGet(t *testing.T) { + pq := New(compare.Int) + l := []int{32, 10, 53, 78, 90, 1, 4} + for _, v := range l { + pq.Push(v) + } + + if v, ok := pq.Get(0); ok { t.Error(v) } - for i := 0; i < 10; i++ { - t.Error(pq.Pop()) + if v, ok := pq.Get(70); ok { + t.Error(v) + } + + for _, v := range l { + if gv, ok := pq.Get(v); ok { + if gv != v { + t.Error("Get value is error, value is", gv) + } + } + } + +} + +func TestQueueIndex(t *testing.T) { + pq := New(compare.Int) + for _, v := range []int{32, 10, 53, 78, 90, 1, 4} { + pq.Push(v) + } + + l := []int{90, 78, 53, 32, 10, 4, 1} + for i, lv := range l { + + if v, ok := pq.Index(len(l) - i - 1); ok { + if v != l[len(l)-i-1] { + t.Error(v) + } + } else { + t.Error(i, "index is not exist") + } + + if v, ok := pq.Index(i); ok { + if v != lv { + t.Error(v) + } + } else { + t.Error(i, "index is not exist") + } + } + + if v, ok := pq.Index(-1); ok { + if v != 1 { + t.Error(v) + } + } else { + t.Error("-1 index is not exist") + } + + if v, ok := pq.Index(pq.Size()); ok { + t.Error("index is exits", pq.Size(), v) + } + + if v, ok := pq.Index(pq.Size() - 1); !ok { + if v != 1 { + t.Error("the last value is 1 not is ", v) + } + } + + if v, ok := pq.Index(-10); ok { + t.Error("-10 index is exits", v) + } +} + +func BenchmarkQueueGet(b *testing.B) { + + l := loadTestData() + + pq := New(compare.Int) + for _, v := range l { + pq.Push(v) + } + + execCount := 5 + b.N = len(l) * execCount + + b.ResetTimer() + b.StartTimer() + +ALL: + for i := 0; i < execCount; i++ { + for _, v := range l { + if gv, ok := pq.Get(v); !ok { + b.Error(gv) + break ALL + } + } + } +} + +func BenchmarkQueueIndex(b *testing.B) { + + l := loadTestData() + + pq := New(compare.Int) + for _, v := range l { + pq.Push(v) + } + + execCount := 2 + b.N = len(l) * execCount + + b.ResetTimer() + b.StartTimer() + +ALL: + for i := 0; i < execCount; i++ { + for idx := range l { + if v, ok := pq.Index(idx); !ok { + b.Error(v) + break ALL + } + } } } @@ -61,7 +204,7 @@ func BenchmarkPriorityPop(b *testing.B) { pq.Push(v) } - b.N = len(l) / 1000 + b.N = len(l) b.ResetTimer() b.StartTimer() diff --git a/priority_queue/vbt.go b/priority_queue/vbt.go index 272a0c1..993a18e 100644 --- a/priority_queue/vbt.go +++ b/priority_queue/vbt.go @@ -60,19 +60,6 @@ func (tree *vbTree) Size() int { func (tree *vbTree) indexNode(idx int) *tNode { cur := tree.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 { @@ -84,6 +71,19 @@ func (tree *vbTree) indexNode(idx int) *tNode { cur = cur.children[0] } } + } else { + idx = -idx - 1 + 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] + } + } } return nil } @@ -166,10 +166,15 @@ func (tree *vbTree) RemoveIndex(idx int) bool { func (tree *vbTree) removeNode(n *tNode) { if tree.root.size == 1 { tree.root = nil + tree.top = nil // return n return } + if tree.top == n { + tree.top = tree.iter.GetPrev(n, 1) + } + ls, rs := getChildrenSize(n) if ls == 0 && rs == 0 { p := n.parent @@ -208,11 +213,12 @@ func (tree *vbTree) removeNode(n *tNode) { cparent := cur.parent // 修改为interface 交换 - n.value, cur.value = cur.value, n.value + // n.value, cur.value = cur.value, n.value + tree.replace(n, cur) // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 if cparent == n { - tree.fixSizeWithRemove(n) + tree.fixSizeWithRemove(cur) } else { tree.fixSizeWithRemove(cparent) } @@ -431,15 +437,21 @@ func (tree *vbTree) Put(key interface{}) { tNode := &tNode{value: key, size: 1} if tree.root == nil { tree.root = tNode + tree.top = tNode return } + if tree.Compare(key, tree.top.value) > 0 { + tree.top = tNode + } + for cur := tree.root; ; { if cur.size > 8 { factor := cur.size / 10 // or factor = 1 - if cur.children[1].size >= cur.children[0].size*2+factor || cur.children[0].size >= cur.children[1].size*2+factor { - cur = tree.fixSize(cur) + ls, rs := cur.children[0].size, cur.children[1].size + if rs >= ls*2+factor || ls >= rs*2+factor { + cur = tree.fixSize(cur, ls, rs) } } @@ -457,6 +469,7 @@ func (tree *vbTree) Put(key interface{}) { tree.rrotate3(cur.parent) } } + return } cur = cur.children[0] @@ -636,6 +649,24 @@ func setChild(cur *tNode, cidx int, child *tNode) { } } +func (tree *vbTree) replace(old, new *tNode) { + + setChild(new, 0, old.children[0]) + setChild(new, 1, old.children[1]) + + if old.parent == nil { + tree.root = new + } else { + if old.parent.children[1] == old { + old.parent.children[1] = new + } else { + old.parent.children[0] = new + } + } + new.size = old.size + new.parent = old.parent +} + func (tree *vbTree) takeParent(token, person *tNode) { if token.parent == nil { tree.root = person @@ -739,55 +770,6 @@ func (tree *vbTree) rlrotate(cur *tNode) *tNode { lrn.size = getChildrenSumSize(lrn) + 1 return lrn - - // 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 (tree *vbTree) replace(old, new *tNode) { - - new.children[0] = old.children[0] - new.children[1] = old.children[1] - - if old.parent == nil { - tree.root = new - } else { - if old.parent.children[1] == old { - old.parent.children[1] = new - } else { - old.parent.children[0] = new - } - } - } func (tree *vbTree) rrotate3(cur *tNode) *tNode { @@ -877,16 +859,17 @@ func (tree *vbTree) fixSizeWithRemove(cur *tNode) { cur.size-- if cur.size > 8 { factor := cur.size / 10 // or factor = 1 - if cur.children[1].size >= cur.children[0].size*2+factor || cur.children[0].size >= cur.children[1].size*2+factor { - cur = tree.fixSize(cur) + ls, rs := getChildrenSize(cur) + if rs >= ls*2+factor || ls >= rs*2+factor { + cur = tree.fixSize(cur, ls, rs) } } cur = cur.parent } } -func (tree *vbTree) fixSize(cur *tNode) *tNode { - if cur.children[0].size > cur.children[1].size { +func (tree *vbTree) fixSize(cur *tNode, ls, rs int) *tNode { + if ls > rs { llsize, lrsize := getChildrenSize(cur.children[0]) if lrsize > llsize { return tree.rlrotate(cur) diff --git a/priority_queue/vbt_test.go b/priority_queue/vbt_test.go index 0b4501f..e51ed8d 100644 --- a/priority_queue/vbt_test.go +++ b/priority_queue/vbt_test.go @@ -194,15 +194,26 @@ func TestPutStable(t *testing.T) { for i := 0; i < 40; i++ { v := randomdata.Number(0, 100) tree.Put(v) + + t.Error(tree.top, v) + // t.Error(i, v) + // t.Error(tree.debugString()) + } + + for i := 0; i < 40; i++ { + v, _ := tree.Index(0) + tree.RemoveIndex(0) t.Error(i, v) - t.Error(tree.debugString()) + if tree.top != nil { + t.Error(tree.top) + } } } func TestPutComparatorRandom(t *testing.T) { - for n := 0; n < 50000; n++ { + for n := 0; n < 30000; n++ { tree := newVBT(compare.Int) godsavl := avltree.NewWithIntComparator() @@ -330,7 +341,7 @@ func TestTravalsal(t *testing.T) { func TestRemoveAll(t *testing.T) { ALL: - for c := 0; c < 10000; c++ { + for c := 0; c < 20000; c++ { tree := newVBT(compare.Int) gods := avltree.NewWithIntComparator() var l []int @@ -353,12 +364,10 @@ ALL: s1 := spew.Sprint(tree.Values()) s2 := spew.Sprint(gods.Values()) if s1 != s2 { - // t.Error("avl remove error", "avlsize = ", tree.Size()) - // t.Error(beforce) - // t.Error(after) - // t.Error(tree.root, i, l[i]) - // t.Error(s1) - // t.Error(s2) + t.Error("avl remove error", "avlsize = ", tree.Size()) + t.Error(tree.root, i, l[i]) + t.Error(s1) + t.Error(s2) break ALL } } diff --git a/vbt/vbt.go b/vbt/vbt.go index 90072d3..fb96c10 100644 --- a/vbt/vbt.go +++ b/vbt/vbt.go @@ -436,8 +436,9 @@ func (tree *Tree) Put(key interface{}) { if cur.size > 8 { factor := cur.size / 10 // or factor = 1 - if cur.children[1].size >= cur.children[0].size*2+factor || cur.children[0].size >= cur.children[1].size*2+factor { - tree.fixSize(cur) + ls, rs := cur.children[0].size, cur.children[1].size + if rs >= ls*2+factor || ls >= rs*2+factor { + tree.fixSize(cur, ls, rs) } } @@ -866,16 +867,17 @@ func (tree *Tree) fixSizeWithRemove(cur *Node) { cur.size-- if cur.size > 8 { factor := cur.size / 10 // or factor = 1 - if cur.children[1].size >= cur.children[0].size*2+factor || cur.children[0].size >= cur.children[1].size*2+factor { - tree.fixSize(cur) + ls, rs := getChildrenSize(cur) + if rs >= ls*2+factor || ls >= rs*2+factor { + tree.fixSize(cur, ls, rs) } } cur = cur.parent } } -func (tree *Tree) fixSize(cur *Node) { - if cur.children[0].size > cur.children[1].size { +func (tree *Tree) fixSize(cur *Node, ls, rs int) { + if ls > rs { llsize, lrsize := getChildrenSize(cur.children[0]) if lrsize > llsize { tree.rlrotate(cur) diff --git a/vbt/vbt_test.go b/vbt/vbt_test.go index 26775b6..4da788f 100644 --- a/vbt/vbt_test.go +++ b/vbt/vbt_test.go @@ -319,13 +319,13 @@ func TestTravalsal(t *testing.T) { func TestRemoveAll(t *testing.T) { ALL: - for c := 0; c < 5000; c++ { + for c := 0; c < 10000; c++ { tree := New(compare.Int) gods := avltree.NewWithIntComparator() var l []int m := make(map[int]int) - for i := 0; len(l) < 20; i++ { + for i := 0; len(l) < 100; i++ { v := randomdata.Number(0, 100000) if _, ok := m[v]; !ok { m[v] = v @@ -335,7 +335,7 @@ ALL: } } - for i := 0; i < 20; i++ { + for i := 0; i < 100; i++ { tree.Remove(l[i]) gods.Remove(l[i]) @@ -391,6 +391,23 @@ ALL: } } +func BenchmarkSkipRemove(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() + + for _, v := range l { + sl.Remove(v) + } +} + func BenchmarkSkipListGet(b *testing.B) { sl := skiplist.New(skiplist.Int) l := loadTestData() diff --git a/vbtkey/vbtkey.go b/vbtkey/vbtkey.go index 3f9f0bd..144fae6 100644 --- a/vbtkey/vbtkey.go +++ b/vbtkey/vbtkey.go @@ -433,8 +433,9 @@ func (tree *Tree) Put(key, value interface{}) { if cur.size > 8 { factor := cur.size / 10 // or factor = 1 - if cur.children[1].size >= cur.children[0].size*2+factor || cur.children[0].size >= cur.children[1].size*2+factor { - tree.fixSize(cur) + ls, rs := cur.children[0].size, cur.children[1].size + if rs >= ls*2+factor || ls >= rs*2+factor { + tree.fixSize(cur, ls, rs) } } @@ -870,56 +871,17 @@ func (tree *Tree) fixSizeWithRemove(cur *Node) { cur.size-- if cur.size > 8 { factor := cur.size / 10 // or factor = 1 - if cur.children[1].size >= cur.children[0].size*2+factor || cur.children[0].size >= cur.children[1].size*2+factor { - tree.fixSize(cur) + ls, rs := getChildrenSize(cur) + if rs >= ls*2+factor || ls >= rs*2+factor { + tree.fixSize(cur, ls, rs) } } 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) fix6Size(cur *Node, lefts, rigths int) { - if lefts > rigths { - l := cur.children[0] - llsize, lrsize := getChildrenSize(l) - if lrsize > llsize { - tree.rlrotate(cur) - } else { - tree.rrotate(cur) - } - } else { - r := cur.children[1] - rlsize, rrsize := getChildrenSize(r) - if rlsize > rrsize { - tree.lrrotate(cur) - } else { - tree.lrotate(cur) - } - } -} - -func (tree *Tree) fixSize(cur *Node) { - if cur.children[0].size > cur.children[1].size { +func (tree *Tree) fixSize(cur *Node, ls, rs int) { + if ls > rs { llsize, lrsize := getChildrenSize(cur.children[0]) if lrsize > llsize { tree.rlrotate(cur) diff --git a/vbtkey/vbtkey_test.go b/vbtkey/vbtkey_test.go index 62cc94b..f0b2064 100644 --- a/vbtkey/vbtkey_test.go +++ b/vbtkey/vbtkey_test.go @@ -325,7 +325,7 @@ ALL: var l []int m := make(map[int]int) - for i := 0; len(l) < 20; i++ { + for i := 0; len(l) < 50; i++ { v := randomdata.Number(0, 100000) if _, ok := m[v]; !ok { m[v] = v @@ -335,7 +335,7 @@ ALL: } } - for i := 0; i < 20; i++ { + for i := 0; i < 50; i++ { tree.Remove(l[i]) gods.Remove(l[i])