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