From 8f5c7b5210cc98d3dbb95772100531429a26a138 Mon Sep 17 00:00:00 2001 From: huangsimin Date: Wed, 18 Mar 2020 16:27:34 +0800 Subject: [PATCH] find key value error --- priority_queuekey/{vbt.go => vbtkey.go} | 0 tree/avl/iterator_test.go | 35 + tree/avldup/iterator_test.go | 35 + tree/avlkey/iterator_test.go | 35 + tree/avlkeydup/iterator_test.go | 35 + tree/rsync.sh | 21 + tree/tree.go | 16 +- tree/vbt/iterator_test.go | 35 + tree/{vbtdupkey => vbtdup}/iterator.go | 2 +- tree/vbtdup/iterator_test.go | 35 + tree/vbtdup/vbtdup.go | 1018 +++++++++++++++++ tree/vbtdup/vbtdup_test.go | 844 ++++++++++++++ tree/vbtkey/iterator_test.go | 35 + tree/vbtkey/vbtkey.go | 5 +- tree/vbtkey/vbtkey_test.go | 2 +- tree/vbtkeydup/iterator.go | 252 ++++ tree/vbtkeydup/iterator_test.go | 35 + tree/{vbtdupkey => vbtkeydup}/vbtdupkey.go | 4 +- .../vbtdupkey_test.go | 2 +- 19 files changed, 2437 insertions(+), 9 deletions(-) rename priority_queuekey/{vbt.go => vbtkey.go} (100%) create mode 100644 tree/avl/iterator_test.go create mode 100644 tree/avldup/iterator_test.go create mode 100644 tree/avlkey/iterator_test.go create mode 100644 tree/avlkeydup/iterator_test.go create mode 100644 tree/rsync.sh create mode 100644 tree/vbt/iterator_test.go rename tree/{vbtdupkey => vbtdup}/iterator.go (99%) create mode 100644 tree/vbtdup/iterator_test.go create mode 100644 tree/vbtdup/vbtdup.go create mode 100644 tree/vbtdup/vbtdup_test.go create mode 100644 tree/vbtkey/iterator_test.go create mode 100644 tree/vbtkeydup/iterator.go create mode 100644 tree/vbtkeydup/iterator_test.go rename tree/{vbtdupkey => vbtkeydup}/vbtdupkey.go (99%) rename tree/{vbtdupkey => vbtkeydup}/vbtdupkey_test.go (99%) diff --git a/priority_queuekey/vbt.go b/priority_queuekey/vbtkey.go similarity index 100% rename from priority_queuekey/vbt.go rename to priority_queuekey/vbtkey.go diff --git a/tree/avl/iterator_test.go b/tree/avl/iterator_test.go new file mode 100644 index 0000000..a6f96a3 --- /dev/null +++ b/tree/avl/iterator_test.go @@ -0,0 +1,35 @@ +package avl + +import ( + "sort" + "testing" + + "github.com/474420502/focus/compare" +) + +func TestIerator(t *testing.T) { + tree := New(compare.Int) + l := []int{5, 10, 100, 30, 40, 70, 45, 35, 23} + for _, v := range l { + tree.Put(v) + } + + sort.Ints(l) + + iter := tree.Iterator() + iter.ToHead() + for i := 0; iter.Next(); i++ { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } + iter.ToTail() + iter.Prev() + for i := len(l) - 1; iter.Next(); i-- { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } +} diff --git a/tree/avldup/iterator_test.go b/tree/avldup/iterator_test.go new file mode 100644 index 0000000..10352d0 --- /dev/null +++ b/tree/avldup/iterator_test.go @@ -0,0 +1,35 @@ +package avldup + +import ( + "sort" + "testing" + + "github.com/474420502/focus/compare" +) + +func TestIerator(t *testing.T) { + tree := New(compare.Int) + l := []int{5, 10, 100, 30, 40, 70, 45, 35, 23} + for _, v := range l { + tree.Put(v) + } + + sort.Ints(l) + + iter := tree.Iterator() + iter.ToHead() + for i := 0; iter.Next(); i++ { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } + iter.ToTail() + iter.Prev() + for i := len(l) - 1; iter.Next(); i-- { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } +} diff --git a/tree/avlkey/iterator_test.go b/tree/avlkey/iterator_test.go new file mode 100644 index 0000000..61ecd2d --- /dev/null +++ b/tree/avlkey/iterator_test.go @@ -0,0 +1,35 @@ +package avlkey + +import ( + "sort" + "testing" + + "github.com/474420502/focus/compare" +) + +func TestIerator(t *testing.T) { + tree := New(compare.Int) + l := []int{5, 10, 100, 30, 40, 70, 45, 35, 23} + for _, v := range l { + tree.Put(v, v) + } + + sort.Ints(l) + + iter := tree.Iterator() + iter.ToHead() + for i := 0; iter.Next(); i++ { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } + iter.ToTail() + iter.Prev() + for i := len(l) - 1; iter.Next(); i-- { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } +} diff --git a/tree/avlkeydup/iterator_test.go b/tree/avlkeydup/iterator_test.go new file mode 100644 index 0000000..e7a22d0 --- /dev/null +++ b/tree/avlkeydup/iterator_test.go @@ -0,0 +1,35 @@ +package avlkeydup + +import ( + "sort" + "testing" + + "github.com/474420502/focus/compare" +) + +func TestIerator(t *testing.T) { + tree := New(compare.Int) + l := []int{5, 10, 100, 30, 40, 70, 45, 35, 23} + for _, v := range l { + tree.Put(v, v) + } + + sort.Ints(l) + + iter := tree.Iterator() + iter.ToHead() + for i := 0; iter.Next(); i++ { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } + iter.ToTail() + iter.Prev() + for i := len(l) - 1; iter.Next(); i-- { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } +} diff --git a/tree/rsync.sh b/tree/rsync.sh new file mode 100644 index 0000000..0f662c1 --- /dev/null +++ b/tree/rsync.sh @@ -0,0 +1,21 @@ + +rsync() { + FILE_NAME=$3 #iterator_test.go + SRC_DIR_NAME=$1 #vbtkey dir + DEST_DIR_NAME=$2 # vbtdupkey dir + + cp ./$SRC_DIR_NAME/$FILE_NAME ./$DEST_DIR_NAME/$FILE_NAME + sed -i "s/package $SRC_DIR_NAME/package ${DEST_DIR_NAME}/" ./$DEST_DIR_NAME/$FILE_NAME +} + +# 同步iterator_test +for dst in "vbtkeydup" "avlkey" "avlkeydup" +do + rsync "vbtkey" $dst "iterator_test.go" +done + +# 同步iterator_test +for dst in "vbtdup" "avl" "avldup" +do + rsync "vbt" $dst "iterator_test.go" +done diff --git a/tree/tree.go b/tree/tree.go index 5d47b60..9e21766 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -1,6 +1,6 @@ package tree -// IBSTreeKey Compare函数可以自定义所以key不一定value, 可以是value结构体中一个属性 +// IBSTreeKey Compare函数可以自定义所以key不一定value, 可以是value结构体中一个属性 type IBSTreeKey interface { String() string Size() int @@ -21,11 +21,23 @@ type IBSTree interface { Clear() // Values 返回先序遍历的值 Values() []interface{} - Get(key interface{}) (interface{}, bool) + Get(value interface{}) (interface{}, bool) Put(value interface{}) Traversal(every func(v interface{}) bool, traversalMethod ...interface{}) } +type IBSTreeDup interface { + String() string + Size() int + Remove(key interface{}) (interface{}, bool) + Clear() + // Values 返回先序遍历的值 + Values() []interface{} + Get(value interface{}) (interface{}, bool) + Put(value interface{}) bool + Traversal(every func(v interface{}) bool, traversalMethod ...interface{}) +} + type IBSTreeDupKey interface { String() string Size() int diff --git a/tree/vbt/iterator_test.go b/tree/vbt/iterator_test.go new file mode 100644 index 0000000..b15a3f6 --- /dev/null +++ b/tree/vbt/iterator_test.go @@ -0,0 +1,35 @@ +package vbt + +import ( + "sort" + "testing" + + "github.com/474420502/focus/compare" +) + +func TestIerator(t *testing.T) { + tree := New(compare.Int) + l := []int{5, 10, 100, 30, 40, 70, 45, 35, 23} + for _, v := range l { + tree.Put(v) + } + + sort.Ints(l) + + iter := tree.Iterator() + iter.ToHead() + for i := 0; iter.Next(); i++ { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } + iter.ToTail() + iter.Prev() + for i := len(l) - 1; iter.Next(); i-- { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } +} diff --git a/tree/vbtdupkey/iterator.go b/tree/vbtdup/iterator.go similarity index 99% rename from tree/vbtdupkey/iterator.go rename to tree/vbtdup/iterator.go index afafeb8..3e09f89 100644 --- a/tree/vbtdupkey/iterator.go +++ b/tree/vbtdup/iterator.go @@ -1,4 +1,4 @@ -package vbtkey +package vbtdup import ( lastack "github.com/474420502/focus/stack/listarraystack" diff --git a/tree/vbtdup/iterator_test.go b/tree/vbtdup/iterator_test.go new file mode 100644 index 0000000..b69f267 --- /dev/null +++ b/tree/vbtdup/iterator_test.go @@ -0,0 +1,35 @@ +package vbtdup + +import ( + "sort" + "testing" + + "github.com/474420502/focus/compare" +) + +func TestIerator(t *testing.T) { + tree := New(compare.Int) + l := []int{5, 10, 100, 30, 40, 70, 45, 35, 23} + for _, v := range l { + tree.Put(v) + } + + sort.Ints(l) + + iter := tree.Iterator() + iter.ToHead() + for i := 0; iter.Next(); i++ { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } + iter.ToTail() + iter.Prev() + for i := len(l) - 1; iter.Next(); i-- { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } +} diff --git a/tree/vbtdup/vbtdup.go b/tree/vbtdup/vbtdup.go new file mode 100644 index 0000000..3c75421 --- /dev/null +++ b/tree/vbtdup/vbtdup.go @@ -0,0 +1,1018 @@ +package vbtdup + +import ( + "github.com/davecgh/go-spew/spew" + + "github.com/474420502/focus/compare" + "github.com/474420502/focus/tree" +) + +type Node struct { + children [2]*Node + parent *Node + size int + value interface{} +} + +func (n *Node) String() string { + if n == nil { + return "nil" + } + + p := "nil" + if n.parent != nil { + p = spew.Sprint(n.parent.value) + } + return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.size) + ")" +} + +type Tree struct { + root *Node + Compare compare.Compare + + iter *Iterator +} + +func assertImplementation() { + var _ tree.IBSTreeDup = (*Tree)(nil) +} + +func New(Compare compare.Compare) *Tree { + return &Tree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)} +} + +func (tree *Tree) String() string { + str := "VBTree-Dup\n" + if tree.root == nil { + return str + "nil" + } + output(tree.root, "", true, &str) + return str +} + +func (tree *Tree) Iterator() *Iterator { + return initIterator(tree) +} + +func (tree *Tree) Size() int { + if tree.root == nil { + return 0 + } + return tree.root.size +} + +func (tree *Tree) IndexNode(idx int) *Node { + 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 { + return cur + } else if idx < rs { + cur = cur.children[1] + } else { + idx = idx - rs - 1 + cur = cur.children[0] + } + } + } + return nil +} + +func (tree *Tree) Index(idx int) (interface{}, bool) { + n := tree.IndexNode(idx) + if n != nil { + return n.value, true + } + return nil, false +} + +func (tree *Tree) IndexRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1 + + if idx1^idx2 < 0 { + if idx1 < 0 { + idx1 = tree.root.size + idx1 + } else { + idx2 = tree.root.size + idx2 + } + } + + if idx1 > idx2 { + ok = true + if idx1 >= tree.root.size { + idx1 = tree.root.size - 1 + ok = false + } + + n := tree.IndexNode(idx1) + tree.iter.SetNode(n) + iter := tree.iter + result = make([]interface{}, 0, idx1-idx2) + for i := idx2; i <= idx1; i++ { + if iter.Prev() { + result = append(result, iter.Value()) + } else { + ok = false + return + } + } + + return + + } else { + ok = true + if idx2 >= tree.root.size { + idx2 = tree.root.size - 1 + ok = false + } + + if n := tree.IndexNode(idx1); n != nil { + tree.iter.SetNode(n) + iter := tree.iter + result = make([]interface{}, 0, idx2-idx1) + for i := idx1; i <= idx2; i++ { + if iter.Next() { + result = append(result, iter.Value()) + } else { + ok = false + return + } + } + + return + } + + } + + return nil, false +} + +func (tree *Tree) RemoveIndex(idx int) (interface{}, bool) { + n := tree.IndexNode(idx) + if n != nil { + tree.RemoveNode(n) + return n.value, true + } + return nil, false +} + +func (tree *Tree) RemoveNode(n *Node) { + if tree.root.size == 1 { + tree.root = nil + // return n + return + } + + ls, rs := getChildrenSize(n) + if ls == 0 && rs == 0 { + p := n.parent + p.children[getRelationship(n)] = nil + tree.fixSizeWithRemove(p) + // return n + return + } + + var cur *Node + if ls > rs { + cur = n.children[0] + for cur.children[1] != nil { + cur = cur.children[1] + } + + cleft := cur.children[0] + cur.parent.children[getRelationship(cur)] = cleft + if cleft != nil { + cleft.parent = cur.parent + } + + } else { + cur = n.children[1] + for cur.children[0] != nil { + cur = cur.children[0] + } + + cright := cur.children[1] + cur.parent.children[getRelationship(cur)] = cright + + if cright != nil { + cright.parent = cur.parent + } + } + + cparent := cur.parent + // 修改为interface 交换 + n.value, cur.value = cur.value, n.value + + // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 + if cparent == n { + tree.fixSizeWithRemove(n) + } else { + tree.fixSizeWithRemove(cparent) + } + + // return cur + return +} + +func (tree *Tree) Remove(key interface{}) (interface{}, bool) { + + if n, ok := tree.GetNode(key); ok { + tree.RemoveNode(n) + return n.value, true + } + // return nil + return nil, false +} + +func (tree *Tree) Clear() { + tree.root = nil + tree.iter = NewIteratorWithCap(nil, 16) +} + +// Values 返回先序遍历的值 +func (tree *Tree) Values() []interface{} { + mszie := 0 + if tree.root != nil { + mszie = tree.root.size + } + result := make([]interface{}, 0, mszie) + tree.Traversal(func(v interface{}) bool { + result = append(result, v) + return true + }, LDR) + return result +} + +func (tree *Tree) GetRange(k1, k2 interface{}) (result []interface{}) { + c := tree.Compare(k2, k1) + switch c { + case 1: + + var min, max *Node + resultmin := tree.getArountNode(k1) + resultmax := tree.getArountNode(k2) + for i := 1; i < 3 && min == nil; i++ { + min = resultmin[i] + } + + for i := 1; i > -1 && max == nil; i-- { + max = resultmax[i] + } + + if max == nil { + return []interface{}{} + } + + result = make([]interface{}, 0, 16) + + tree.iter.SetNode(min) + iter := tree.iter + for iter.Next() { + result = append(result, iter.Value()) + if iter.cur == max { + break + } + } + case -1: + + var min, max *Node + resultmin := tree.getArountNode(k2) + resultmax := tree.getArountNode(k1) + for i := 1; i < 3 && min == nil; i++ { + min = resultmin[i] + } + for i := 1; i > -1 && max == nil; i-- { + max = resultmax[i] + } + + if min == nil { + return []interface{}{} + } + + result = make([]interface{}, 0, 16) + + tree.iter.SetNode(max) + iter := tree.iter + for iter.Prev() { + result = append(result, iter.Value()) + if iter.cur == min { + break + } + } + case 0: + if n, ok := tree.GetNode(k1); ok { + return []interface{}{n.value} + } + return []interface{}{} + } + + return +} + +func (tree *Tree) Get(key interface{}) (interface{}, bool) { + n, ok := tree.GetNode(key) + if ok { + return n.value, true + } + return n, false +} + +func (tree *Tree) GetAround(key interface{}) (result [3]interface{}) { + an := tree.getArountNode(key) + for i, n := range an { + if n != nil { + result[i] = n.value + } + } + return +} + +func (tree *Tree) getArountNode(key interface{}) (result [3]*Node) { + var last *Node + var lastc int + + for n := tree.root; n != nil; { + last = n + c := tree.Compare(key, n.value) + switch c { + case -1: + n = n.children[0] + lastc = c + case 1: + n = n.children[1] + lastc = c + case 0: + tree.iter.SetNode(n) + iter := tree.iter + iter.Prev() + for iter.Prev() { + if tree.Compare(iter.cur.value, n.value) == 0 { + n = iter.cur + } else { + break + } + } + result[1] = n + n = nil + default: + panic("Get Compare only is allowed in -1, 0, 1") + } + } + + switch lastc { + case 1: + + if result[1] != nil { + + result[0] = tree.iter.GetPrev(result[1], 1) + result[2] = tree.iter.GetNext(result[1], 1) + } else { + result[0] = last + result[2] = tree.iter.GetNext(last, 1) + } + + case -1: + + if result[1] != nil { + result[0] = tree.iter.GetPrev(result[1], 1) + result[2] = tree.iter.GetNext(result[1], 1) + } else { + result[2] = last + result[0] = tree.iter.GetPrev(last, 1) + } + + case 0: + + if result[1] == nil { + return + } + result[0] = tree.iter.GetPrev(result[1], 1) + result[2] = tree.iter.GetNext(result[1], 1) + } + return +} + +func (tree *Tree) GetNode(key interface{}) (*Node, bool) { + + for n := tree.root; n != nil; { + switch c := tree.Compare(key, n.value); c { + case -1: + n = n.children[0] + case 1: + n = n.children[1] + case 0: + + tree.iter.SetNode(n) + iter := tree.iter + iter.Prev() + for iter.Prev() { + if tree.Compare(iter.cur.value, n.value) == 0 { + n = iter.cur + } else { + break + } + } + return n, true + default: + panic("Get Compare only is allowed in -1, 0, 1") + } + } + return nil, false +} + +// Put return bool +func (tree *Tree) Put(value interface{}) (isInsert bool) { + + node := &Node{value: value, size: 1} + if tree.root == nil { + tree.root = node + return true + } + + for cur := tree.root; ; { + + if cur.size > 8 { + factor := cur.size / 10 // or factor = 1 + ls, rs := cur.children[0].size, cur.children[1].size + if rs >= ls*2+factor || ls >= rs*2+factor { + tree.fixSize(cur, ls, rs) + } + } + + c := tree.Compare(value, cur.value) + switch { + case c < 0: + if cur.children[0] == nil { + cur.children[0] = node + node.parent = cur + + for temp := cur; temp != nil; temp = temp.parent { + temp.size++ + } + + if cur.parent != nil && cur.parent.size == 3 { + if cur.parent.children[0] == nil { + tree.lrrotate3(cur.parent) + } else { + tree.rrotate3(cur.parent) + } + } + return true + } + cur = cur.children[0] + case c > 0: + if cur.children[1] == nil { + cur.children[1] = node + node.parent = cur + + for temp := cur; temp != nil; temp = temp.parent { + temp.size++ + } + + if cur.parent != nil && cur.parent.size == 3 { + if cur.parent.children[1] == nil { + tree.rlrotate3(cur.parent) + } else { + tree.lrotate3(cur.parent) + } + } + return true + } + cur = cur.children[1] + default: + cur.value = value + return false + } + + } +} + +// TraversalMethod 遍历模式 +type TraversalMethod int + +const ( + // L = left R = right D = Value(dest) + _ TraversalMethod = iota + //DLR 先值 然后左递归 右递归 下面同理 + DLR + //LDR 先从左边有序访问到右边 从小到大 + LDR + // LRD 同理 + LRD + + // DRL 同理 + DRL + + // RDL 先从右边有序访问到左边 从大到小 + RDL + + // RLD 同理 + RLD +) + +// Traversal 遍历的方法 默认是LDR 从小到大 Compare 为 l < r +func (tree *Tree) Traversal(every func(v interface{}) bool, traversalMethod ...interface{}) { + if tree.root == nil { + return + } + + method := LDR + if len(traversalMethod) != 0 { + method = traversalMethod[0].(TraversalMethod) + } + + switch method { + case DLR: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !every(cur.value) { + return false + } + if !traverasl(cur.children[0]) { + return false + } + if !traverasl(cur.children[1]) { + return false + } + return true + } + traverasl(tree.root) + case LDR: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !traverasl(cur.children[0]) { + return false + } + if !every(cur.value) { + return false + } + if !traverasl(cur.children[1]) { + return false + } + return true + } + traverasl(tree.root) + case LRD: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !traverasl(cur.children[0]) { + return false + } + if !traverasl(cur.children[1]) { + return false + } + if !every(cur.value) { + return false + } + return true + } + traverasl(tree.root) + case DRL: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !every(cur.value) { + return false + } + if !traverasl(cur.children[0]) { + return false + } + if !traverasl(cur.children[1]) { + return false + } + return true + } + traverasl(tree.root) + case RDL: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !traverasl(cur.children[1]) { + return false + } + if !every(cur.value) { + return false + } + if !traverasl(cur.children[0]) { + return false + } + return true + } + traverasl(tree.root) + case RLD: + var traverasl func(cur *Node) bool + traverasl = func(cur *Node) bool { + if cur == nil { + return true + } + if !traverasl(cur.children[1]) { + return false + } + if !traverasl(cur.children[0]) { + return false + } + if !every(cur.value) { + return false + } + return true + } + traverasl(tree.root) + } +} + +func (tree *Tree) lrrotate3(cur *Node) { + const l = 1 + const r = 0 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + cur.children[r] = mov + mov.parent = cur + + cur.children[l] = movparent + movparent.children[r] = nil + + cur.children[r] = mov + mov.parent = cur + + // cur.size = 3 + // cur.children[r].size = 1 + cur.children[l].size = 1 +} + +func (tree *Tree) lrrotate(cur *Node) { + + const l = 1 + const r = 0 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + if mov.children[l] != nil { + movparent.children[r] = mov.children[l] + movparent.children[r].parent = movparent + //movparent.children[r].child = l + } else { + movparent.children[r] = nil + } + + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + //mov.children[l].child = l + } else { + mov.children[l] = nil + } + + if cur.children[r] != nil { + mov.children[r] = cur.children[r] + mov.children[r].parent = mov + } else { + mov.children[r] = nil + } + + cur.children[r] = mov + mov.parent = cur + + movparent.size = getChildrenSumSize(movparent) + 1 + mov.size = getChildrenSumSize(mov) + 1 + cur.size = getChildrenSumSize(cur) + 1 +} + +func (tree *Tree) rlrotate3(cur *Node) { + const l = 0 + const r = 1 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + cur.children[r] = mov + mov.parent = cur + + cur.children[l] = movparent + movparent.children[r] = nil + + cur.children[r] = mov + mov.parent = cur + + // cur.size = 3 + // cur.children[r].size = 1 + cur.children[l].size = 1 +} + +func (tree *Tree) rlrotate(cur *Node) { + + const l = 0 + const r = 1 + + movparent := cur.children[l] + mov := movparent.children[r] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + if mov.children[l] != nil { + movparent.children[r] = mov.children[l] + movparent.children[r].parent = movparent + } else { + movparent.children[r] = nil + } + + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + } else { + mov.children[l] = nil + } + + if cur.children[r] != nil { + mov.children[r] = cur.children[r] + mov.children[r].parent = mov + } else { + mov.children[r] = nil + } + + cur.children[r] = mov + mov.parent = cur + + movparent.size = getChildrenSumSize(movparent) + 1 + mov.size = getChildrenSumSize(mov) + 1 + cur.size = getChildrenSumSize(cur) + 1 +} + +func (tree *Tree) rrotate3(cur *Node) { + const l = 0 + const r = 1 + // 1 right 0 left + mov := cur.children[l] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + cur.children[r] = mov + + cur.children[l] = mov.children[l] + cur.children[l].parent = cur + + mov.children[l] = nil + + mov.size = 1 +} + +func (tree *Tree) rrotate(cur *Node) { + + const l = 0 + const r = 1 + // 1 right 0 left + mov := cur.children[l] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + // mov.children[l]不可能为nil + mov.children[l].parent = cur + + cur.children[l] = mov.children[l] + + // 解决mov节点孩子转移的问题 + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + } else { + mov.children[l] = nil + } + + if cur.children[r] != nil { + mov.children[r] = cur.children[r] + mov.children[r].parent = mov + } else { + mov.children[r] = nil + } + + // 连接转移后的节点 由于mov只是与cur交换值,parent不变 + cur.children[r] = mov + + mov.size = getChildrenSumSize(mov) + 1 + cur.size = getChildrenSumSize(cur) + 1 +} + +func (tree *Tree) lrotate3(cur *Node) { + const l = 1 + const r = 0 + // 1 right 0 left + mov := cur.children[l] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + cur.children[r] = mov + + cur.children[l] = mov.children[l] + cur.children[l].parent = cur + + mov.children[l] = nil + + mov.size = 1 +} + +func (tree *Tree) lrotate(cur *Node) { + + const l = 1 + const r = 0 + // 1 right 0 left + mov := cur.children[l] + + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + // mov.children[l]不可能为nil + mov.children[l].parent = cur + + cur.children[l] = mov.children[l] + + // 解决mov节点孩子转移的问题 + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + } else { + mov.children[l] = nil + } + + if cur.children[r] != nil { + mov.children[r] = cur.children[r] + mov.children[r].parent = mov + } else { + mov.children[r] = nil + } + + // 连接转移后的节点 由于mov只是与cur交换值,parent不变 + cur.children[r] = mov + + mov.size = getChildrenSumSize(mov) + 1 + cur.size = getChildrenSumSize(cur) + 1 +} + +func getChildrenSumSize(cur *Node) int { + return getSize(cur.children[0]) + getSize(cur.children[1]) +} + +func getChildrenSize(cur *Node) (int, int) { + return getSize(cur.children[0]), getSize(cur.children[1]) +} + +func getSize(cur *Node) int { + if cur == nil { + return 0 + } + return cur.size +} + +func (tree *Tree) fixSizeWithRemove(cur *Node) { + for cur != nil { + cur.size-- + if cur.size > 8 { + factor := cur.size / 10 // or factor = 1 + ls, rs := getChildrenSize(cur) + if rs >= ls*2+factor || ls >= rs*2+factor { + tree.fixSize(cur, ls, rs) + } + } else if cur.size == 3 { + if cur.children[0] == nil { + if cur.children[1].children[0] == nil { + tree.lrotate3(cur) + } else { + tree.lrrotate3(cur) + } + } else if cur.children[1] == nil { + if cur.children[0].children[1] == nil { + tree.rrotate3(cur) + } else { + tree.rlrotate3(cur) + } + } + } + cur = cur.parent + } +} + +func (tree *Tree) fixSize(cur *Node, ls, rs int) { + if ls > rs { + llsize, lrsize := getChildrenSize(cur.children[0]) + if lrsize > llsize { + tree.rlrotate(cur) + } else { + tree.rrotate(cur) + } + } else { + rlsize, rrsize := getChildrenSize(cur.children[1]) + if rlsize > rrsize { + tree.lrrotate(cur) + } else { + tree.lrotate(cur) + } + } +} + +func output(node *Node, prefix string, isTail bool, str *string) { + + if node.children[1] != nil { + newPrefix := prefix + if isTail { + newPrefix += "│ " + } else { + newPrefix += " " + } + output(node.children[1], newPrefix, false, str) + } + *str += prefix + if isTail { + *str += "└── " + } else { + *str += "┌── " + } + + *str += spew.Sprint(node.value) + ":" + spew.Sprint(node.value) + "\n" + + if node.children[0] != nil { + newPrefix := prefix + if isTail { + newPrefix += " " + } else { + newPrefix += "│ " + } + output(node.children[0], newPrefix, true, str) + } + +} + +func outputfordebug(node *Node, prefix string, isTail bool, str *string) { + + if node.children[1] != nil { + newPrefix := prefix + if isTail { + newPrefix += "│ " + } else { + newPrefix += " " + } + outputfordebug(node.children[1], newPrefix, false, str) + } + *str += prefix + if isTail { + *str += "└── " + } else { + *str += "┌── " + } + + suffix := "(" + parentv := "" + if node.parent == nil { + parentv = "nil" + } else { + parentv = spew.Sprint(node.parent.value) + } + suffix += parentv + "|" + spew.Sprint(node.size) + ")" + *str += spew.Sprint(node.value) + suffix + "\n" + + if node.children[0] != nil { + newPrefix := prefix + if isTail { + newPrefix += " " + } else { + newPrefix += "│ " + } + outputfordebug(node.children[0], newPrefix, true, str) + } +} + +func (tree *Tree) debugString() string { + str := "VBTree-Dup\n" + if tree.root == nil { + return str + "nil" + } + outputfordebug(tree.root, "", true, &str) + return str +} diff --git a/tree/vbtdup/vbtdup_test.go b/tree/vbtdup/vbtdup_test.go new file mode 100644 index 0000000..020f7e7 --- /dev/null +++ b/tree/vbtdup/vbtdup_test.go @@ -0,0 +1,844 @@ +package vbtdup + +import ( + "bytes" + "encoding/gob" + "io/ioutil" + "log" + "sort" + "testing" + + "github.com/Pallinder/go-randomdata" + "github.com/davecgh/go-spew/spew" + + "github.com/474420502/focus/compare" +) + +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 TestIteratorHeadTail(t *testing.T) { + tree := New(compare.Int) + l := []int{1, 7, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15, 100} + for _, v := range l { + tree.Put(v) + } + + iter := tree.Iterator() + iter.ToHead() // 从小到大 + iter.Next() + if iter.Value() != 1 { + t.Error("value error", iter.Value()) + } + + iter.ToTail() + iter.Prev() + if iter.Value() != 100 { + t.Error("value error", iter.Value()) + } + + for n := 0; n < 500; n++ { + tree := New(compare.Int) + var results []int + for i := 0; i < 50; i++ { + v := randomdata.Number(0, 5000) + if ok := tree.Put(v); ok { + results = append(results, v) + } + } + result := tree.GetAround(5001) + + iter = tree.Iterator() + iter.ToTail() + iter.Prev() + if iter.Value() != result[0] { + t.Error("ToTail error", result, iter.Value()) + } + + result = tree.GetAround(-1) + + iter.ToHead() + iter.Next() + if iter.Value() != result[2] { + t.Error("ToTail error", result, iter.Value()) + } + + } + +} + +func TestLargePushRemove(t *testing.T) { + for n := 0; n < 10; n++ { + tree := New(compare.Int) + var results []int + for i := 0; i < 50000; i++ { + v := randomdata.Number(0, 100000000) + if ok := tree.Put(v); ok { + results = append(results, v) + } + + } + + if tree.Size() != len(results) { + t.Error("Szie error", tree.Size(), len(results)) + } + + for i := 0; i < len(results)-10; i++ { + tree.Remove(results[i]) + } + + results = results[len(results)-10:] + if tree.Size() != 10 { + t.Error("Szie error") + } + sort.Slice(results, func(i, j int) bool { + if results[i] < results[j] { + return true + } + return false + }) + if spew.Sprint(results) != spew.Sprint(tree.Values()) { + t.Error("tree is error") + } + + for i := 0; i < 10; i++ { + v1 := results[i] + v2, ok := tree.Index(i) + if !ok { + t.Error("not ok") + } + if v1 != v2 { + t.Error("v1(", v1, ") != v2(", v2, ")??") + } + } + + tree.Clear() + if tree.String() != "VBTree-Dup\nnil" { + t.Error("tree String is error") + } + } +} + +func TestRemoveIndex(t *testing.T) { + tree := New(compare.Int) + l := []int{7, 14, 14, 14, 16, 1, 40, 15} + for _, v := range l { + tree.Put(v) + } + + // [1 7 14 14 14 15 16 40] + var result string + result = spew.Sprint(tree.Values()) + if result != "[1 7 14 15 16 40]" { + t.Error("result = ", result, " should be [1 7 14 15 16 40]") + } + + tree.RemoveIndex(3) + result = spew.Sprint(tree.Values()) + if result != "[1 7 14 16 40]" { + t.Error("result is error") + } + + tree.RemoveIndex(-1) + result = spew.Sprint(tree.Values()) + if result != "[1 7 14 16]" { + t.Error("result is error") + } + + tree.RemoveIndex(0) + result = spew.Sprint(tree.Values()) + if result != "[7 14 16]" { + t.Error("result is error") + } + + if tree.Size() != 3 { + t.Error("size is error") + } + + for tree.Size() != 0 { + tree.RemoveIndex(0) + } + + if tree.root != nil { + t.Error("tree roor is not error") + } +} + +func TestIndexRange(t *testing.T) { + tree := New(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 15 16 17 20 21 30 40 50] + // t.Error(tree.Values(), tree.Size()) + // t.Error(tree.debugString()) + + var result string + result = spew.Sprint(tree.IndexRange(0, 5)) + if result != "[3 7 14 15 16 17] true" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(2, 5)) + if result != "[14 15 16 17] true" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(5, 100)) + if result != "[17 20 21 30 40 50] false" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(10, 0)) // size = 11, index max = 10 + if result != "[50 40 30 21 20 17 16 15 14 7 3] true" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(11, 0)) // size = 11, index max = 10 + if result != "[50 40 30 21 20 17 16 15 14 7 3] false" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(4, 1)) // size = 11, index max = 10 + if result != "[16 15 14 7] true" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(-1, -5)) // size = 11, index max = 10 + if result != "[50 40 30 21 20] true" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(-1, -11)) // size = 11, index max = 0 - 10 (-1,-11) + if result != "[50 40 30 21 20 17 16 15 14 7 3] true" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(-1, -12)) // size = 11, index max = 0 - 10 (-1,-11) + if result != "[50 40 30 21 20 17 16 15 14 7 3] false" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(-5, -1)) // size = 11, index max = 0 - 10 (-1,-11) + if result != "[20 21 30 40 50] true" { + t.Error(result) + } + + // [3 7 14 15 16 17 20 21 30 40 50] + result = spew.Sprint(tree.IndexRange(-5, 5)) // + if result != "[20 17] true" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(5, -5)) // + if result != "[17 20] true" { + t.Error(result) + } + + result = spew.Sprint(tree.IndexRange(-1, 6)) // + if result != "[50 40 30 21 20] true" { + t.Error(result) + } + +} + +func TestGetAround(t *testing.T) { + tree := New(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 != "[ 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 50]" { + t.Error(tree.Values()) + t.Error("tree.GetAround(40)) is error", Result) + t.Error(tree.debugString()) + } + + Result = spew.Sprint(tree.GetAround(50)) + if Result != "[40 50 ]" { + t.Error(tree.Values()) + t.Error("tree.GetAround(50)) is error", Result) + t.Error(tree.debugString()) + } + + Result = spew.Sprint(tree.GetAround(18)) + if Result != "[17 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 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 != "[ 3]" { + t.Error(tree.Values()) + t.Error("2 is not in list, tree.GetAround(2)) is error", Result) + t.Error(tree.debugString()) + } + + Result = spew.Sprint(tree.GetAround(100)) + if Result != "[50 ]" { + t.Error(tree.Values()) + t.Error("50 is not in list, tree.GetAround(50)) is error", Result) + t.Error(tree.debugString()) + } + +} + +// // for test error case + +// func TestPutComparatorRandom(t *testing.T) { + +// for n := 0; n < 300000; n++ { +// tree := New(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, 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 := New(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 TestDupGetRange(t *testing.T) { + tree := New(compare.Int) + for _, v := range []int{5, 10, 13, 5, 17, 1, 2, 10, 40, 30, 1} { + tree.Put(v) + } + + result := tree.GetRange(0, 20) + if spew.Sprint(result) != "[1 2 5 10 13 17]" { + t.Error(result) + } + + result = tree.GetRange(0, 8) + if spew.Sprint(result) != "[1 2 5]" { + t.Error(result) + } + + result = tree.GetRange(-5, -1) + if spew.Sprint(result) != "[]" { + t.Error(result) + } + + result = tree.GetRange(7, 20) + if spew.Sprint(result) != "[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 5 2 1]" { + t.Error(result) + } + + result = tree.GetRange(30, 20) + if spew.Sprint(result) != "[30]" { + t.Error(result) + } + +} + +func TestGetRange(t *testing.T) { + tree := New(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 := New(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 := New(compare.Int) +// gods := avltree.NewWithIntComparator() +// var l []int +// m := make(map[int]int) + +// for i := 0; len(l) < 50; i++ { +// v := randomdata.Number(0, 100000) +// if _, ok := m[v]; !ok { +// m[v] = v +// l = append(l, v) +// tree.Put(v, v) +// gods.Put(v, v) +// } +// } + +// for i := 0; i < 50; 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 := New(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, 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 BenchmarkGetRange(b *testing.B) { + +// } + +// func BenchmarkIndexRange(b *testing.B) { +// tree := New(compare.Int) +// l := loadTestData() +// b.N = len(l) + +// for _, v := range l { +// tree.Put(v, 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 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 { +// sl.Get(v) +// // e := sl.Get(v) +// // var result [50]interface{} +// // for i := 0; i < 50 && e != nil; i++ { +// // result[i] = e.Value +// // e = e.Next() +// // } +// } +// } +// } + +// 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 := New(compare.Int) + +// l := loadTestData() +// b.N = len(l) + +// for _, v := range l { +// tree.Put(v, v) +// } + +// b.ResetTimer() +// b.StartTimer() +// iter := tree.Iterator() +// b.N = 0 +// for iter.Next() { +// b.N++ +// } +// for iter.Prev() { +// b.N++ +// } +// for iter.Next() { +// b.N++ +// } +// b.Log(b.N, len(l)) +// } + +// func BenchmarkRemove(b *testing.B) { +// tree := New(compare.Int) + +// 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) { + +// tree := New(compare.Int) + +// 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 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 := 50 +// b.N = len(l) * execCount +// for i := 0; i < execCount; i++ { +// tree := New(compare.Int) +// for _, v := range l { +// tree.Put(v, v) +// } +// } +// } + +// func TestPutStable(t *testing.T) { + +// } + +// func BenchmarkGodsRBPut(b *testing.B) { +// l := loadTestData() + +// b.ResetTimer() +// b.StartTimer() + +// execCount := 50 +// b.N = len(l) * execCount +// for i := 0; i < execCount; i++ { +// tree := redblacktree.NewWithIntComparator() +// 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/tree/vbtkey/iterator_test.go b/tree/vbtkey/iterator_test.go new file mode 100644 index 0000000..0535860 --- /dev/null +++ b/tree/vbtkey/iterator_test.go @@ -0,0 +1,35 @@ +package vbtkey + +import ( + "sort" + "testing" + + "github.com/474420502/focus/compare" +) + +func TestIerator(t *testing.T) { + tree := New(compare.Int) + l := []int{5, 10, 100, 30, 40, 70, 45, 35, 23} + for _, v := range l { + tree.Put(v, v) + } + + sort.Ints(l) + + iter := tree.Iterator() + iter.ToHead() + for i := 0; iter.Next(); i++ { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } + iter.ToTail() + iter.Prev() + for i := len(l) - 1; iter.Next(); i-- { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } +} diff --git a/tree/vbtkey/vbtkey.go b/tree/vbtkey/vbtkey.go index 604b08b..9d5cfcd 100644 --- a/tree/vbtkey/vbtkey.go +++ b/tree/vbtkey/vbtkey.go @@ -27,6 +27,7 @@ func (n *Node) String() string { return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.size) + ")" } +// Tree increasing type Tree struct { root *Node Compare compare.Compare @@ -43,7 +44,7 @@ func New(Compare compare.Compare) *Tree { } func (tree *Tree) String() string { - str := "AVLTree\n" + str := "VBTree-Key\n" if tree.root == nil { return str + "nil" } @@ -347,7 +348,7 @@ func (tree *Tree) getArountNode(key interface{}) (result [3]*Node) { for n := tree.root; n != nil; { last = n - c := tree.Compare(key, n.value) + c := tree.Compare(key, n.key) switch c { case -1: n = n.children[0] diff --git a/tree/vbtkey/vbtkey_test.go b/tree/vbtkey/vbtkey_test.go index 78ffd64..98977ed 100644 --- a/tree/vbtkey/vbtkey_test.go +++ b/tree/vbtkey/vbtkey_test.go @@ -66,7 +66,7 @@ func TestLargePushRemove(t *testing.T) { } tree.Clear() - if tree.String() != "AVLTree\nnil" { + if tree.String() != "VBTree-Key\nnil" { t.Error("tree String is error") } } diff --git a/tree/vbtkeydup/iterator.go b/tree/vbtkeydup/iterator.go new file mode 100644 index 0000000..4e0bb10 --- /dev/null +++ b/tree/vbtkeydup/iterator.go @@ -0,0 +1,252 @@ +package vbtkeydup + +import ( + lastack "github.com/474420502/focus/stack/listarraystack" +) + +type Iterator struct { + dir int + up *Node + cur *Node + tstack *lastack.Stack + // curnext *Node +} + +func initIterator(avltree *Tree) *Iterator { + iter := &Iterator{tstack: lastack.New()} + iter.up = avltree.root + return iter +} + +func NewIterator(n *Node) *Iterator { + iter := &Iterator{tstack: lastack.New()} + iter.up = n + return iter +} + +func NewIteratorWithCap(n *Node, cap int) *Iterator { + iter := &Iterator{tstack: lastack.NewWithCap(cap)} + iter.up = n + return iter +} + +func (iter *Iterator) GetNode() *Node { + return iter.cur +} + +func (iter *Iterator) ToHead() { + if iter.cur == nil { + iter.cur = iter.up + } + + for iter.cur.parent != nil { + iter.cur = iter.cur.parent + } + + for iter.cur.children[0] != nil { + iter.cur = iter.cur.children[0] + } + iter.SetNode(iter.cur) + iter.cur = nil +} + +func (iter *Iterator) ToTail() { + + if iter.cur == nil { + iter.cur = iter.up + } + + for iter.cur.parent != nil { + iter.cur = iter.cur.parent + } + + for iter.cur.children[1] != nil { + iter.cur = iter.cur.children[1] + } + iter.SetNode(iter.cur) + iter.cur = nil +} + +func (iter *Iterator) SetNode(n *Node) { + iter.up = n + iter.dir = 0 + iter.tstack.Clear() +} + +func (iter *Iterator) Key() interface{} { + return iter.cur.key +} + +func (iter *Iterator) Value() interface{} { + return iter.cur.value +} + +func (iter *Iterator) GetNext(cur *Node, idx int) *Node { + + // iter := NewIterator(cur) + iter.SetNode(cur) + iter.curPushNextStack(iter.up) + iter.up = iter.getNextUp(iter.up) + + for i := 0; i < idx; i++ { + + if iter.tstack.Size() == 0 { + if iter.up == nil { + return nil + } + iter.tstack.Push(iter.up) + iter.up = iter.getNextUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + if i == idx-1 { + return iter.cur + } + iter.curPushNextStack(iter.cur) + } else { + return nil + } + } + + return cur +} + +func (iter *Iterator) Next() (result bool) { + + if iter.dir > -1 { + if iter.dir == 1 && iter.cur != nil { + iter.tstack.Clear() + iter.curPushNextStack(iter.cur) + iter.up = iter.getNextUp(iter.cur) + } + iter.dir = -1 + } + + 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 + } + + return false +} +func (iter *Iterator) GetPrev(cur *Node, idx int) *Node { + + // iter := NewIterator(cur) + iter.SetNode(cur) + iter.curPushPrevStack(iter.up) + iter.up = iter.getPrevUp(iter.up) + + for i := 0; i < idx; i++ { + + if iter.tstack.Size() == 0 { + if iter.up == nil { + return nil + } + iter.tstack.Push(iter.up) + iter.up = iter.getPrevUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + if i == idx-1 { + return iter.cur + } + iter.curPushPrevStack(iter.cur) + } else { + return nil + } + } + + return cur +} + +func (iter *Iterator) Prev() (result bool) { + + if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev) + if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈 + iter.tstack.Clear() + iter.curPushPrevStack(iter.cur) // 把当前cur计算的回朔 + iter.up = iter.getPrevUp(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.getPrevUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + iter.curPushPrevStack(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) getPrevUp(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) curPushPrevStack(cur *Node) { + Prev := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值 + + if Prev != nil { + iter.tstack.Push(Prev) + for Prev.children[1] != nil { + Prev = Prev.children[1] + iter.tstack.Push(Prev) // 入栈 用于回溯 + } + } +} + +func (iter *Iterator) getNextUp(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) curPushNextStack(cur *Node) { + next := cur.children[1] + + if next != nil { + iter.tstack.Push(next) + for next.children[0] != nil { + next = next.children[0] + iter.tstack.Push(next) + } + } +} diff --git a/tree/vbtkeydup/iterator_test.go b/tree/vbtkeydup/iterator_test.go new file mode 100644 index 0000000..8305263 --- /dev/null +++ b/tree/vbtkeydup/iterator_test.go @@ -0,0 +1,35 @@ +package vbtkeydup + +import ( + "sort" + "testing" + + "github.com/474420502/focus/compare" +) + +func TestIerator(t *testing.T) { + tree := New(compare.Int) + l := []int{5, 10, 100, 30, 40, 70, 45, 35, 23} + for _, v := range l { + tree.Put(v, v) + } + + sort.Ints(l) + + iter := tree.Iterator() + iter.ToHead() + for i := 0; iter.Next(); i++ { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } + iter.ToTail() + iter.Prev() + for i := len(l) - 1; iter.Next(); i-- { + + if iter.Value() != l[i] { + t.Error(iter.Value(), l[i]) + } + } +} diff --git a/tree/vbtdupkey/vbtdupkey.go b/tree/vbtkeydup/vbtdupkey.go similarity index 99% rename from tree/vbtdupkey/vbtdupkey.go rename to tree/vbtkeydup/vbtdupkey.go index 8075e70..693114c 100644 --- a/tree/vbtdupkey/vbtdupkey.go +++ b/tree/vbtkeydup/vbtdupkey.go @@ -1,4 +1,4 @@ -package vbtkey +package vbtkeydup import ( "github.com/davecgh/go-spew/spew" @@ -347,7 +347,7 @@ func (tree *Tree) getArountNode(key interface{}) (result [3]*Node) { for n := tree.root; n != nil; { last = n - c := tree.Compare(key, n.value) + c := tree.Compare(key, n.key) switch c { case -1: n = n.children[0] diff --git a/tree/vbtdupkey/vbtdupkey_test.go b/tree/vbtkeydup/vbtdupkey_test.go similarity index 99% rename from tree/vbtdupkey/vbtdupkey_test.go rename to tree/vbtkeydup/vbtdupkey_test.go index 22f7166..aea219d 100644 --- a/tree/vbtdupkey/vbtdupkey_test.go +++ b/tree/vbtkeydup/vbtdupkey_test.go @@ -1,4 +1,4 @@ -package vbtkey +package vbtkeydup import ( "bytes"