From b7e6045064f13a8e3151dbe02d543dc65efb40da Mon Sep 17 00:00:00 2001 From: huangsimin Date: Wed, 13 Mar 2019 19:09:24 +0800 Subject: [PATCH] TODO: avlkey --- avl/avl.go | 4 + avl/avl_test.go | 61 ++++ avl/iterator.go | 103 ++++--- avldup/avldup.go | 139 +++++++-- avldup/avldup_test.go | 33 +-- avldup/iterator.go | 145 ++++++++++ avlkey/avl.go | 635 ++++++++++++++++++++++++++++++++++++++++++ avlkey/avl_test.go | 503 +++++++++++++++++++++++++++++++++ avlkey/iterator.go | 145 ++++++++++ 9 files changed, 1675 insertions(+), 93 deletions(-) create mode 100644 avldup/iterator.go create mode 100644 avlkey/avl.go create mode 100644 avlkey/avl_test.go create mode 100644 avlkey/iterator.go diff --git a/avl/avl.go b/avl/avl.go index edd4914..8852480 100644 --- a/avl/avl.go +++ b/avl/avl.go @@ -57,6 +57,10 @@ func (avl *AVL) Iterator() *Iterator { return initIterator(avl) } +func (avl *AVL) Size() int { + return avl.size +} + func (avl *AVL) Remove(v interface{}) *Node { if n, ok := avl.GetNode(v); ok { diff --git a/avl/avl_test.go b/avl/avl_test.go index 06d92cd..6cc2757 100644 --- a/avl/avl_test.go +++ b/avl/avl_test.go @@ -1,8 +1,10 @@ package avl import ( + "log" "testing" + "github.com/emirpasic/gods/maps/hashmap" "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/trees/avltree" @@ -347,7 +349,31 @@ func BenchmarkGodsRemove(b *testing.B) { } } +func BenchmarkGoGet(b *testing.B) { + avl := make(map[int]int) + + b.N = CompartorSize + for i := 0; i < b.N; i++ { + avl[randomdata.Number(0, NumberMax)] = i + } + + b.ResetTimer() + b.StartTimer() + b.N = CompartorSize + + var v int + var ok bool + for i := 0; i < b.N; i++ { + v, ok = avl[randomdata.Number(0, NumberMax)] + } + + if ok && v == 1 { + v = 1 + } +} + func BenchmarkGet(b *testing.B) { + avl := New(utils.IntComparator) b.N = CompartorSize @@ -392,6 +418,41 @@ func BenchmarkGodsAvlGet(b *testing.B) { } } +func BenchmarkGoPut(b *testing.B) { + avl := make(map[int]int) + + for i := 0; i < 100000; i++ { + avl[randomdata.Number(0, NumberMax)] = i + } + + b.ResetTimer() + b.StartTimer() + b.N = CompartorSize + + for i := 0; i < b.N; i++ { + avl[randomdata.Number(0, NumberMax)] = i + } + + log.Println(avl[12]) +} + +func BenchmarkGodsHashmap(b *testing.B) { + avl := hashmap.New() + + b.N = CompartorSize * 10 + for i := 0; i < b.N; i++ { + avl.Put(randomdata.Number(0, NumberMax), i) + } + + // b.ResetTimer() + // b.StartTimer() + // b.N = CompartorSize + + // for i := 0; i < b.N; i++ { + // avl[randomdata.Number(0, NumberMax)] = i + // } +} + func BenchmarkPut(b *testing.B) { avl := New(utils.IntComparator) diff --git a/avl/iterator.go b/avl/iterator.go index cf0230f..65c9a31 100644 --- a/avl/iterator.go +++ b/avl/iterator.go @@ -24,26 +24,70 @@ func (iter *Iterator) Value() interface{} { return iter.cur.value } +func (iter *Iterator) Left() bool { + if iter.cur.children[0] != nil { + iter.dir = 0 + iter.cur = iter.cur.children[0] + return true + } + return false +} + +func (iter *Iterator) Right() bool { + if iter.cur.children[1] != nil { + iter.dir = 0 + iter.cur = iter.cur.children[1] + return true + } + return false +} + +func (iter *Iterator) Prev() (result bool) { + + if iter.dir > -1 { + if iter.dir == 1 && iter.cur != nil { + iter.tstack.Clear() + iter.curPushPrevStack(iter.cur) + iter.up = iter.getPrevUp(iter.cur) + } + iter.dir = -1 + } + + if iter.tstack.Size() == 0 { + if iter.up == nil { + return false + } + iter.tstack.Push(iter.up) + iter.up = iter.getPrevUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + iter.curPushPrevStack(iter.cur) + return true + } + + return false +} + func (iter *Iterator) Next() (result bool) { - if iter.dir < 1 { - if iter.dir == -1 { - if iter.cur != nil { - iter.tstack.Clear() - iter.curPushNextStack(iter.cur) - iter.up = iter.getNextUp(iter.cur) - } + if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev) + if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈 + iter.tstack.Clear() + iter.curPushNextStack(iter.cur) // 把当前cur计算的逆向回朔 + iter.up = iter.getNextUp(iter.cur) // cur 寻找下个要计算up } iter.dir = 1 } + // 如果栈空了, 把up的递归计算入栈, 重新计算 下次的up值 if iter.tstack.Size() == 0 { - if iter.up != nil { - iter.tstack.Push(iter.up) - iter.up = iter.getNextUp(iter.up) - } else { + if iter.up == nil { return false } + iter.tstack.Push(iter.up) + iter.up = iter.getNextUp(iter.up) } if v, ok := iter.tstack.Pop(); ok { @@ -52,6 +96,7 @@ func (iter *Iterator) Next() (result bool) { return true } + // 如果再次计算的栈为空, 则只能返回false return false } @@ -66,13 +111,13 @@ func (iter *Iterator) getNextUp(cur *Node) *Node { } func (iter *Iterator) curPushNextStack(cur *Node) { - next := cur.children[0] + next := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值 if next != nil { iter.tstack.Push(next) for next.children[1] != nil { next = next.children[1] - iter.tstack.Push(next) + iter.tstack.Push(next) // 入栈 用于回溯 } } } @@ -98,35 +143,3 @@ func (iter *Iterator) curPushPrevStack(cur *Node) { } } } - -func (iter *Iterator) Prev() (result bool) { - - if iter.dir > -1 { - - if iter.dir == 1 { - if iter.cur != nil { - iter.tstack.Clear() - iter.curPushPrevStack(iter.cur) - iter.up = iter.getPrevUp(iter.cur) - } - } - iter.dir = -1 - } - - if iter.tstack.Size() == 0 { - if iter.up != nil { - iter.tstack.Push(iter.up) - iter.up = iter.getPrevUp(iter.up) - } else { - return false - } - } - - if v, ok := iter.tstack.Pop(); ok { - iter.cur = v.(*Node) - iter.curPushPrevStack(iter.cur) - return true - } - - return false -} diff --git a/avldup/avldup.go b/avldup/avldup.go index ec550e9..a068bae 100644 --- a/avldup/avldup.go +++ b/avldup/avldup.go @@ -1,4 +1,4 @@ -package bstree +package avldup import ( "github.com/davecgh/go-spew/spew" @@ -14,6 +14,13 @@ type Node struct { value interface{} } +// func (n *Node) String() string { +// if n == nil { +// return "nil" +// } +// return spew.Sprint(n.value) +// } + func (n *Node) String() string { if n == nil { return "nil" @@ -26,17 +33,17 @@ func (n *Node) String() string { return spew.Sprint(n.value) + "(" + p + "-" + spew.Sprint(n.child) + "|" + spew.Sprint(n.height) + ")" } -type AVLTree struct { +type AVLDup struct { root *Node size int comparator utils.Comparator } -func New(comparator utils.Comparator) *AVLTree { - return &AVLTree{comparator: comparator} +func New(comparator utils.Comparator) *AVLDup { + return &AVLDup{comparator: comparator} } -func (avl *AVLTree) String() string { +func (avl *AVLDup) String() string { if avl.size == 0 { return "" } @@ -46,7 +53,15 @@ func (avl *AVLTree) String() string { return str } -func (avl *AVLTree) Remove(v interface{}) *Node { +func (avl *AVLDup) Iterator() *Iterator { + return initIterator(avl) +} + +func (avl *AVLDup) Size() int { + return avl.size +} + +func (avl *AVLDup) Remove(v interface{}) *Node { if n, ok := avl.GetNode(v); ok { @@ -105,11 +120,10 @@ func (avl *AVLTree) Remove(v interface{}) *Node { return n } - return nil } -func (avl *AVLTree) Get(v interface{}) (interface{}, bool) { +func (avl *AVLDup) Get(v interface{}) (interface{}, bool) { n, ok := avl.GetNode(v) if ok { return n.value, true @@ -117,7 +131,70 @@ func (avl *AVLTree) Get(v interface{}) (interface{}, bool) { return n, false } -func (avl *AVLTree) GetNode(v interface{}) (*Node, bool) { +func (avl *AVLDup) GetAround(v interface{}) (result [3]interface{}) { + an := avl.GetAroundNode(v) + for i, n := range an { + if n.value != nil { + result[i] = n.value + } + } + return +} + +func (avl *AVLDup) GetAroundNode(v interface{}) (result [3]*Node) { + n := avl.root + + for { + + if n == nil { + return + } + + lastc := 0 + switch c := avl.comparator(v, n.value); c { + case -1: + if c != -lastc { + result[0] = n + } + lastc = c + n = n.children[0] + case 1: + if c != -lastc { + result[2] = n + } + lastc = c + n = n.children[1] + case 0: + + switch lastc { + case -1: + if n.children[1] != nil { + result[0] = n.children[1] + } + case 1: + if n.children[0] != nil { + result[2] = n.children[0] + } + case 0: + + if n.children[1] != nil { + result[0] = n.children[1] + } + if n.children[0] != nil { + result[2] = n.children[0] + } + + result[1] = n + return + } + + default: + panic("Get comparator only is allowed in -1, 0, 1") + } + + } +} +func (avl *AVLDup) GetNode(v interface{}) (*Node, bool) { n := avl.root for n != nil { @@ -136,11 +213,11 @@ func (avl *AVLTree) GetNode(v interface{}) (*Node, bool) { return nil, false } -func (avl *AVLTree) Put(v interface{}) { - avl.size++ - node := &Node{value: v} - if avl.size == 1 { - avl.root = node +func (avl *AVLDup) Put(v interface{}) { + + if avl.size == 0 { + avl.root = &Node{value: v} + avl.size++ return } @@ -151,9 +228,11 @@ func (avl *AVLTree) Put(v interface{}) { for { if cur == nil { + node := &Node{value: v} parent.children[child] = node node.parent = parent node.child = child + avl.size++ if node.parent.height == 0 { avl.fixPutHeight(node.parent) @@ -162,19 +241,23 @@ func (avl *AVLTree) Put(v interface{}) { } parent = cur - c := avl.comparator(node.value, cur.value) - if c > -1 { // right + c := avl.comparator(v, cur.value) + switch c { // right + case 1: child = 1 cur = cur.children[child] - } else { + case -1: child = 0 cur = cur.children[child] + case 0: + cur.value = v + return } } } -func (avl *AVLTree) replace(old *Node, newN *Node) { +func (avl *AVLDup) replace(old *Node, newN *Node) { if old.parent == nil { setChild(newN, 0, old.children[0]) @@ -211,16 +294,16 @@ func setChildNotNil(p *Node, child int, node *Node) { node.parent = p } -func (avl *AVLTree) debugString() string { +func (avl *AVLDup) debugString() string { if avl.size == 0 { return "" } - str := "AVLTree" + "\n" + str := "AVLDup" + "\n" outputfordebug(avl.root, "", true, &str) return str } -func (avl *AVLTree) TraversalBreadth() (result []interface{}) { +func (avl *AVLDup) TraversalBreadth() (result []interface{}) { var traverasl func(cur *Node) traverasl = func(cur *Node) { if cur == nil { @@ -234,7 +317,7 @@ func (avl *AVLTree) TraversalBreadth() (result []interface{}) { return } -func (avl *AVLTree) TraversalDepth(leftright int) (result []interface{}) { +func (avl *AVLDup) TraversalDepth(leftright int) (result []interface{}) { if leftright < 0 { var traverasl func(cur *Node) @@ -263,7 +346,7 @@ func (avl *AVLTree) TraversalDepth(leftright int) (result []interface{}) { return } -func (avl *AVLTree) lrrotate(cur *Node) *Node { +func (avl *AVLDup) lrrotate(cur *Node) *Node { r := cur.children[1] rl := r.children[0] @@ -290,7 +373,7 @@ func (avl *AVLTree) lrrotate(cur *Node) *Node { return rl } -func (avl *AVLTree) rlrotate(cur *Node) *Node { +func (avl *AVLDup) rlrotate(cur *Node) *Node { l := cur.children[0] lr := l.children[1] @@ -316,7 +399,7 @@ func (avl *AVLTree) rlrotate(cur *Node) *Node { return lr } -func (avl *AVLTree) rrotate(cur *Node) *Node { +func (avl *AVLDup) rrotate(cur *Node) *Node { l := cur.children[0] @@ -341,7 +424,7 @@ func (avl *AVLTree) rrotate(cur *Node) *Node { return l // 返回前 替换为cur节点的节点, 有利余修复高度 } -func (avl *AVLTree) lrotate(cur *Node) *Node { +func (avl *AVLDup) lrotate(cur *Node) *Node { r := cur.children[1] @@ -398,7 +481,7 @@ func getHeight(cur *Node) int { return cur.height } -func (avl *AVLTree) fixRemoveHeight(cur *Node) { +func (avl *AVLDup) fixRemoveHeight(cur *Node) { for { @@ -445,7 +528,7 @@ func (avl *AVLTree) fixRemoveHeight(cur *Node) { } -func (avl *AVLTree) fixPutHeight(cur *Node) { +func (avl *AVLDup) fixPutHeight(cur *Node) { for { diff --git a/avldup/avldup_test.go b/avldup/avldup_test.go index 8619d42..d37c42d 100644 --- a/avldup/avldup_test.go +++ b/avldup/avldup_test.go @@ -1,4 +1,4 @@ -package bstree +package avldup import ( "testing" @@ -41,7 +41,7 @@ func TestRotate(t *testing.T) { func TestPutStable(t *testing.T) { avl := New(utils.IntComparator) - for _, v := range []int{7, 14, 15, 20, 30, 21} { + for _, v := range []int{7, 14, 15, 20, 30, 21, 7} { t.Error(v) avl.Put(v) t.Error(avl.debugString()) @@ -80,17 +80,12 @@ func TestPutComparatorRandom(t *testing.T) { godsavl := avltree.NewWithIntComparator() content := "" - m := make(map[int]int) - for i := 0; len(m) < 10; i++ { + for i := 0; avl.size < 10; i++ { v := randomdata.Number(0, 65535) - if _, ok := m[v]; !ok { - m[v] = v - content += spew.Sprint(v) + " " - // t.Error(v) - avl.Put(v) - // t.Error(avl.String()) - godsavl.Put(v, v) - } + content += spew.Sprint(v) + " " + avl.Put(v) + godsavl.Put(v, v) + } if avl.String() != godsavl.String() { @@ -165,16 +160,14 @@ ALL: gods := avltree.NewWithIntComparator() var l []int - m := make(map[int]int) - for i := 0; len(l) < 10; i++ { + for i := 0; avl.size < 10; i++ { v := randomdata.Number(0, 100) - if _, ok := m[v]; !ok { - l = append(l, v) - m[v] = v - avl.Put(v) - gods.Put(v, v) - } + + l = append(l, v) + avl.Put(v) + gods.Put(v, v) + } src1 := avl.String() diff --git a/avldup/iterator.go b/avldup/iterator.go new file mode 100644 index 0000000..9a09c27 --- /dev/null +++ b/avldup/iterator.go @@ -0,0 +1,145 @@ +package avldup + +import ( + "474420502.top/eson/structure/lastack" +) + +type Iterator struct { + op *AVLDup + + dir int + up *Node + cur *Node + tstack *lastack.Stack + // curnext *Node +} + +func initIterator(avltree *AVLDup) *Iterator { + iter := &Iterator{op: avltree, tstack: lastack.New()} + iter.up = avltree.root + return iter +} + +func (iter *Iterator) Value() interface{} { + return iter.cur.value +} + +func (iter *Iterator) Left() bool { + if iter.cur.children[0] != nil { + iter.dir = 0 + iter.cur = iter.cur.children[0] + return true + } + return false +} + +func (iter *Iterator) Right() bool { + if iter.cur.children[1] != nil { + iter.dir = 0 + iter.cur = iter.cur.children[1] + return true + } + return false +} + +func (iter *Iterator) Prev() (result bool) { + + if iter.dir > -1 { + if iter.dir == 1 && iter.cur != nil { + iter.tstack.Clear() + iter.curPushPrevStack(iter.cur) + iter.up = iter.getPrevUp(iter.cur) + } + iter.dir = -1 + } + + if iter.tstack.Size() == 0 { + if iter.up == nil { + return false + } + iter.tstack.Push(iter.up) + iter.up = iter.getPrevUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + iter.curPushPrevStack(iter.cur) + return true + } + + return false +} + +func (iter *Iterator) Next() (result bool) { + + if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev) + if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈 + iter.tstack.Clear() + iter.curPushNextStack(iter.cur) // 把当前cur计算的逆向回朔 + iter.up = iter.getNextUp(iter.cur) // cur 寻找下个要计算up + } + iter.dir = 1 + } + + // 如果栈空了, 把up的递归计算入栈, 重新计算 下次的up值 + if iter.tstack.Size() == 0 { + if iter.up == nil { + return false + } + iter.tstack.Push(iter.up) + iter.up = iter.getNextUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + iter.curPushNextStack(iter.cur) + return true + } + + // 如果再次计算的栈为空, 则只能返回false + return false +} + +func (iter *Iterator) getNextUp(cur *Node) *Node { + for cur != nil { + if cur.child == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序 + return cur.parent + } + cur = cur.parent + } + return nil +} + +func (iter *Iterator) curPushNextStack(cur *Node) { + next := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值 + + if next != nil { + iter.tstack.Push(next) + for next.children[1] != nil { + next = next.children[1] + iter.tstack.Push(next) // 入栈 用于回溯 + } + } +} + +func (iter *Iterator) getPrevUp(cur *Node) *Node { + for cur != nil { + if cur.child == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序 + return cur.parent + } + cur = cur.parent + } + return nil +} + +func (iter *Iterator) curPushPrevStack(cur *Node) { + prev := cur.children[1] + + if prev != nil { + iter.tstack.Push(prev) + for prev.children[0] != nil { + prev = prev.children[0] + iter.tstack.Push(prev) + } + } +} diff --git a/avlkey/avl.go b/avlkey/avl.go new file mode 100644 index 0000000..0329ed5 --- /dev/null +++ b/avlkey/avl.go @@ -0,0 +1,635 @@ +package avl + +import ( + "github.com/davecgh/go-spew/spew" + + "github.com/emirpasic/gods/utils" +) + +type Node struct { + children [2]*Node + parent *Node + height int + child int + key, value interface{} +} + +// func (n *Node) String() string { +// if n == nil { +// return "nil" +// } +// return spew.Sprint(n.value) +// } + +func (n *Node) String() string { + if n == nil { + return "nil" + } + + p := "nil" + if n.parent != nil { + p = spew.Sprint(n.parent.value) + } + return spew.Sprint(n.value) + "(" + p + "-" + spew.Sprint(n.child) + "|" + spew.Sprint(n.height) + ")" +} + +type AVL struct { + root *Node + size int + comparator utils.Comparator +} + +func New(comparator utils.Comparator) *AVL { + return &AVL{comparator: comparator} +} + +func (avl *AVL) String() string { + if avl.size == 0 { + return "" + } + str := "AVLTree" + "\n" + output(avl.root, "", true, &str) + + return str +} + +func (avl *AVL) Iterator() *Iterator { + return initIterator(avl) +} + +func (avl *AVL) Size() int { + return avl.size +} + +func (avl *AVL) Remove(v interface{}) *Node { + + if n, ok := avl.GetNode(v); ok { + + avl.size-- + if avl.size == 0 { + avl.root = nil + return n + } + + left := getHeight(n.children[0]) + right := getHeight(n.children[1]) + + if left == -1 && right == -1 { + p := n.parent + p.children[n.child] = nil + avl.fixRemoveHeight(p) + return n + } + + var cur *Node + if left > right { + cur = n.children[0] + for cur.children[1] != nil { + cur = cur.children[1] + } + + cleft := cur.children[0] + cur.parent.children[cur.child] = cleft + if cleft != nil { + cleft.child = cur.child + 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[cur.child] = cright + if cright != nil { + cright.child = cur.child + cright.parent = cur.parent + } + } + + cparent := cur.parent + avl.replace(n, cur) + // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 + if cparent == n { + avl.fixRemoveHeight(cur) + } else { + avl.fixRemoveHeight(cparent) + } + + return n + } + + return nil +} + +func (avl *AVL) Get(v interface{}) (interface{}, bool) { + n, ok := avl.GetNode(v) + if ok { + return n.value, true + } + return n, false +} + +func (avl *AVL) GetAround(v interface{}) (result [3]interface{}) { + an := avl.GetAroundNode(v) + for i, n := range an { + if n.value != nil { + result[i] = n.value + } + } + return +} + +func (avl *AVL) GetAroundNode(v interface{}) (result [3]*Node) { + n := avl.root + + for { + + if n == nil { + return + } + + lastc := 0 + switch c := avl.comparator(v, n.value); c { + case -1: + if c != -lastc { + result[0] = n + } + lastc = c + n = n.children[0] + case 1: + if c != -lastc { + result[2] = n + } + lastc = c + n = n.children[1] + case 0: + + switch lastc { + case -1: + if n.children[1] != nil { + result[0] = n.children[1] + } + case 1: + if n.children[0] != nil { + result[2] = n.children[0] + } + case 0: + + if n.children[1] != nil { + result[0] = n.children[1] + } + if n.children[0] != nil { + result[2] = n.children[0] + } + + result[1] = n + return + } + + default: + panic("Get comparator only is allowed in -1, 0, 1") + } + + } +} +func (avl *AVL) GetNode(v interface{}) (*Node, bool) { + + n := avl.root + for n != nil { + switch c := avl.comparator(v, n.value); c { + case -1: + n = n.children[0] + case 1: + n = n.children[1] + case 0: + return n, true + default: + panic("Get comparator only is allowed in -1, 0, 1") + } + } + + return nil, false +} + +func (avl *AVL) Put(key, value interface{}) { + avl.size++ + node := &Node{key: key, value: value} + if avl.size == 1 { + avl.root = node + return + } + + cur := avl.root + parent := cur.parent + child := -1 + + for { + + if cur == nil { + parent.children[child] = node + node.parent = parent + node.child = child + + if node.parent.height == 0 { + avl.fixPutHeight(node.parent) + } + return + } + + parent = cur + c := avl.comparator(node.key, cur.key) + if c > -1 { // right + child = 1 + cur = cur.children[child] + } else { + child = 0 + cur = cur.children[child] + } + } + +} + +func (avl *AVL) replace(old *Node, newN *Node) { + + if old.parent == nil { + setChild(newN, 0, old.children[0]) + setChild(newN, 1, old.children[1]) + + newN.parent = nil + newN.child = -1 + newN.height = old.height + + avl.root = newN + } else { + + setChild(newN, 0, old.children[0]) + setChild(newN, 1, old.children[1]) + + newN.parent = old.parent + newN.child = old.child + newN.height = old.height + old.parent.children[old.child] = newN + } +} + +func setChild(p *Node, child int, node *Node) { + p.children[child] = node + if node != nil { + node.child = child + node.parent = p + } +} + +func setChildNotNil(p *Node, child int, node *Node) { + p.children[child] = node + node.child = child + node.parent = p +} + +func (avl *AVL) debugString() string { + if avl.size == 0 { + return "" + } + str := "AVL" + "\n" + outputfordebug(avl.root, "", true, &str) + return str +} + +func (avl *AVL) TraversalBreadth() (result []interface{}) { + var traverasl func(cur *Node) + traverasl = func(cur *Node) { + if cur == nil { + return + } + result = append(result, cur.value) + traverasl(cur.children[0]) + traverasl(cur.children[1]) + } + traverasl(avl.root) + return +} + +func (avl *AVL) TraversalDepth(leftright int) (result []interface{}) { + + if leftright < 0 { + var traverasl func(cur *Node) + traverasl = func(cur *Node) { + if cur == nil { + return + } + traverasl(cur.children[0]) + result = append(result, cur.value) + traverasl(cur.children[1]) + } + traverasl(avl.root) + } else { + var traverasl func(cur *Node) + traverasl = func(cur *Node) { + if cur == nil { + return + } + traverasl(cur.children[1]) + result = append(result, cur.value) + traverasl(cur.children[0]) + } + traverasl(avl.root) + } + + return +} + +func (avl *AVL) lrrotate(cur *Node) *Node { + + r := cur.children[1] + rl := r.children[0] + if cur.parent == nil { + avl.root = rl + rl.parent = nil + } else { + setChildNotNil(cur.parent, cur.child, rl) + } + + rll := rl.children[0] + rlr := rl.children[1] + + setChild(cur, 1, rll) + setChild(r, 0, rlr) + + setChildNotNil(rl, 0, cur) + setChildNotNil(rl, 1, r) + + cur.height = getMaxChildrenHeight(cur) + 1 + r.height = getMaxChildrenHeight(r) + 1 + rl.height = getMaxChildrenHeight(rl) + 1 + + return rl +} + +func (avl *AVL) rlrotate(cur *Node) *Node { + + l := cur.children[0] + lr := l.children[1] + if cur.parent == nil { + avl.root = lr + lr.parent = nil + } else { + setChildNotNil(cur.parent, cur.child, lr) + } + + lrr := lr.children[1] + lrl := lr.children[0] + + setChild(cur, 0, lrr) + setChild(l, 1, lrl) + setChildNotNil(lr, 1, cur) + setChildNotNil(lr, 0, l) + + cur.height = getMaxChildrenHeight(cur) + 1 + l.height = getMaxChildrenHeight(l) + 1 + lr.height = getMaxChildrenHeight(lr) + 1 + + return lr +} + +func (avl *AVL) rrotate(cur *Node) *Node { + + l := cur.children[0] + + setChild(cur, 0, l.children[1]) + + l.parent = cur.parent + if cur.parent == nil { + avl.root = l + } else { + cur.parent.children[cur.child] = l + } + l.child = cur.child + + setChildNotNil(l, 1, cur) + // l.children[1] = cur + // cur.child = 1 + // cur.parent = l + + cur.height = getMaxChildrenHeight(cur) + 1 + l.height = getMaxChildrenHeight(l) + 1 + + return l // 返回前 替换为cur节点的节点, 有利余修复高度 +} + +func (avl *AVL) lrotate(cur *Node) *Node { + + r := cur.children[1] + + // 右左节点 链接 当前的右节点 + setChild(cur, 1, r.children[0]) + + // 设置 需要旋转的节点到当前节点的 链条 + r.parent = cur.parent + if cur.parent == nil { + avl.root = r + } else { + cur.parent.children[cur.child] = r + } + r.child = cur.child + + // 当前节点旋转到 左边的 链条 + setChildNotNil(r, 0, cur) + // r.children[0] = cur + // cur.child = 0 + // cur.parent = r + + // 修复改动过的节点高度 先从低开始到高 + cur.height = getMaxChildrenHeight(cur) + 1 + r.height = getMaxChildrenHeight(r) + 1 + + return r +} + +func getMaxAndChildrenHeight(cur *Node) (h1, h2, maxh int) { + h1 = getHeight(cur.children[0]) + h2 = getHeight(cur.children[1]) + if h1 > h2 { + maxh = h1 + } else { + maxh = h2 + } + + return +} + +func getMaxChildrenHeight(cur *Node) int { + h1 := getHeight(cur.children[0]) + h2 := getHeight(cur.children[1]) + if h1 > h2 { + return h1 + } + return h2 +} + +func getHeight(cur *Node) int { + if cur == nil { + return -1 + } + return cur.height +} + +func (avl *AVL) fixRemoveHeight(cur *Node) { + + for { + + lefth, rigthh, lrmax := getMaxAndChildrenHeight(cur) + + // 判断当前节点是否有变化, 如果没变化的时候, 不需要往上修复 + isBreak := false + if cur.height == lrmax+1 { + isBreak = true + } else { + cur.height = lrmax + 1 + } + + // 计算高度的差值 绝对值大于2的时候需要旋转 + diff := lefth - rigthh + if diff < -1 { + r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 + if getHeight(r.children[0]) > getHeight(r.children[1]) { + cur = avl.lrrotate(cur) + } else { + cur = avl.lrotate(cur) + } + } else if diff > 1 { + l := cur.children[0] + if getHeight(l.children[1]) > getHeight(l.children[0]) { + cur = avl.rlrotate(cur) + } else { + cur = avl.rrotate(cur) + } + } else { + + if isBreak { + return + } + + } + + if cur.parent == nil { + return + } + + cur = cur.parent + } + +} + +func (avl *AVL) fixPutHeight(cur *Node) { + + for { + + lefth := getHeight(cur.children[0]) + rigthh := getHeight(cur.children[1]) + + // 计算高度的差值 绝对值大于2的时候需要旋转 + diff := lefth - rigthh + if diff < -1 { + r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 + if getHeight(r.children[0]) > getHeight(r.children[1]) { + cur = avl.lrrotate(cur) + } else { + cur = avl.lrotate(cur) + } + + } else if diff > 1 { + l := cur.children[0] + if getHeight(l.children[1]) > getHeight(l.children[0]) { + cur = avl.rlrotate(cur) + } else { + cur = avl.rrotate(cur) + } + } else { + // 选择一个child的最大高度 + 1为 高度 + if lefth > rigthh { + cur.height = lefth + 1 + } else { + cur.height = rigthh + 1 + } + } + + if cur.parent == nil || cur.height < cur.parent.height { + return + } + cur = cur.parent + } +} + +func output(node *Node, prefix string, isTail bool, str *string) { + + if node.children[1] != nil { + newPrefix := prefix + if isTail { + newPrefix += "│ " + } else { + newPrefix += " " + } + output(node.children[1], newPrefix, false, str) + } + *str += prefix + if isTail { + *str += "└── " + } else { + *str += "┌── " + } + + *str += spew.Sprint(node.value) + "\n" + + if node.children[0] != nil { + newPrefix := prefix + if isTail { + newPrefix += " " + } else { + newPrefix += "│ " + } + output(node.children[0], newPrefix, true, str) + } + +} + +func outputfordebug(node *Node, prefix string, isTail bool, str *string) { + + if node.children[1] != nil { + newPrefix := prefix + if isTail { + newPrefix += "│ " + } else { + newPrefix += " " + } + outputfordebug(node.children[1], newPrefix, false, str) + } + *str += prefix + if isTail { + *str += "└── " + } else { + *str += "┌── " + } + + suffix := "(" + parentv := "" + if node.parent == nil { + parentv = "nil" + } else { + parentv = spew.Sprint(node.parent.value) + } + suffix += parentv + "-" + spew.Sprint(node.child) + "|" + spew.Sprint(node.height) + ")" + *str += spew.Sprint(node.value) + suffix + "\n" + + if node.children[0] != nil { + newPrefix := prefix + if isTail { + newPrefix += " " + } else { + newPrefix += "│ " + } + outputfordebug(node.children[0], newPrefix, true, str) + } +} diff --git a/avlkey/avl_test.go b/avlkey/avl_test.go new file mode 100644 index 0000000..6cc2757 --- /dev/null +++ b/avlkey/avl_test.go @@ -0,0 +1,503 @@ +package avl + +import ( + "log" + "testing" + + "github.com/emirpasic/gods/maps/hashmap" + "github.com/emirpasic/gods/trees/redblacktree" + + "github.com/emirpasic/gods/trees/avltree" + + "github.com/davecgh/go-spew/spew" + + "github.com/Pallinder/go-randomdata" + + "github.com/emirpasic/gods/utils" +) + +func TestRotate(t *testing.T) { + avl := New(utils.IntComparator) + + content := "" + for i := 0; i < 10; i++ { + v := randomdata.Number(0, 1000) + content += spew.Sprint(v) + " " + avl.Put(v) + } + + t.Error(content) + src := avl.String() + t.Error(src) + + lsrc := avl.String() + t.Error(lsrc) + // rrotate(&avl.root) + rsrc := avl.String() + t.Error(rsrc) + + if src == rsrc { + t.Error("src == rsrc") + } +} + +func TestIterator(t *testing.T) { + avl := New(utils.IntComparator) + for _, v := range []int{1, 2, 7, 4, 5, 6, 7, 14, 15, 20, 30, 21, 3} { + // t.Error(v) + avl.Put(v) + + } + t.Error(avl.TraversalDepth(1)) + t.Error(avl.debugString()) + iter := avl.Iterator() + + for iter.Prev() { + t.Error(iter.Value()) + } + t.Error("prev == false", iter.Value(), iter.Prev(), iter.Value()) + + for iter.Next() { + t.Error(iter.Value()) + } + t.Error("next == false", iter.Value(), iter.Next(), iter.Value()) + + for iter.Prev() { + t.Error(iter.Value()) + } + t.Error("prev == false", iter.Value()) + + for i := 0; iter.Next(); i++ { + t.Error(iter.Value()) + if i >= 7 { + break + } + } + t.Error("next == false", iter.Value()) + + for iter.Prev() { + t.Error(iter.Value()) + } + t.Error("prev == false", iter.Value()) +} + +func TestGetAround(t *testing.T) { + avl := New(utils.IntComparator) + for _, v := range []int{7, 14, 15, 20, 30, 21, 40, 40, 50, 3, 40, 40, 40} { + t.Error(v) + avl.Put(v) + t.Error(avl.debugString()) + } + t.Error(avl.TraversalDepth(1)) + t.Error(avl.GetAroundNode(40)) + t.Error(avl.GetAround(40)) +} + +func TestPutStable(t *testing.T) { + avl := New(utils.IntComparator) + for _, v := range []int{7, 14, 15, 20, 30, 21} { + t.Error(v) + avl.Put(v) + t.Error(avl.debugString()) + } + // avl = New(utils.IntComparator) + // for _, v := range []int{88, 77, 80} { + // avl.Put(v) + // t.Error(avl.String()) + // } +} + +func TestDiffPutRandom(t *testing.T) { + avl := New(utils.IntComparator) + godsavl := avltree.NewWithIntComparator() + + content := "" + m := make(map[int]int) + for i := 0; len(m) < 10; i++ { + v := randomdata.Number(0, 10000) + if _, ok := m[v]; !ok { + m[v] = v + content += spew.Sprint(v) + " " + t.Error(v) + avl.Put(v) + t.Error(avl.String()) + godsavl.Put(v, v) + } + } + t.Error(godsavl.String()) +} + +func TestPutComparatorRandom(t *testing.T) { + + for n := 0; n < 1000000; n++ { + avl := New(utils.IntComparator) + godsavl := avltree.NewWithIntComparator() + + content := "" + m := make(map[int]int) + for i := 0; len(m) < 10; i++ { + v := randomdata.Number(0, 65535) + if _, ok := m[v]; !ok { + m[v] = v + content += spew.Sprint(v) + " " + // t.Error(v) + avl.Put(v) + // t.Error(avl.String()) + godsavl.Put(v, v) + } + } + + if avl.String() != godsavl.String() { + t.Error(godsavl.String()) + t.Error(avl.String()) + t.Error(content, n) + break + } + } + + // t.Error(content) + // t.Error(avl.String()) + // t.Error(godsavl.String()) + // t.Error(avl.String() == godsavl.String()) + +} + +func TestGet(t *testing.T) { + avl := New(utils.IntComparator) + for i := 0; i < 15; i++ { + avl.Put(randomdata.Number(0, 1000)) + } + t.Error(avl.String()) + t.Error(avl.Get(500)) +} + +func TestRemoveAll(t *testing.T) { + + for c := 0; c < 10000; c++ { + // f, _ := os.OpenFile("./out.log", os.O_TRUNC|os.O_CREATE|os.O_RDWR, 0666) + // log.SetOutput(f) + + avl := New(utils.IntComparator) + var l []int + for i := 0; i < 100; i++ { + v := randomdata.Number(0, 100000) + l = append(l, v) + avl.Put(v) + } + // defer func() { + // if err := recover(); err != nil { + // panic(avl.String()) + // } + // }() + // log.Println(avl.TraversalBreadth()) + for i := 0; i < 100; i++ { + // log.Println(l[i]) + // log.Println(avl.debugString()) + avl.Remove(l[i]) + } + } +} + +func TestRemove(t *testing.T) { + + // avl := New(utils.IntComparator) + + // var l []int + // for _, v := range []int{86, 97, 9, 61, 37, 45, 97, 43, 95, 8} { + // l = append(l, v) + // avl.Put(v) + // } + + // for i := 0; i < len(l); i++ { + // // log.Println(i) + // log.Println("begin", l[i], avl.debugString()) + // avl.Remove(l[i]) + // log.Println("end", l[i], avl.debugString()) + // } + +ALL: + for N := 0; N < 500000; N++ { + avl := New(utils.IntComparator) + gods := avltree.NewWithIntComparator() + + var l []int + m := make(map[int]int) + + for i := 0; len(l) < 10; i++ { + v := randomdata.Number(0, 100) + if _, ok := m[v]; !ok { + l = append(l, v) + m[v] = v + avl.Put(v) + gods.Put(v, v) + } + } + + src1 := avl.String() + src2 := gods.String() + + for i := 0; i < 10; i++ { + avl.Remove(l[i]) + gods.Remove(l[i]) + if spew.Sprint(gods.Values()) != spew.Sprint(avl.TraversalDepth(-1)) && avl.size != 0 { + // if gods.String() != avl.String() && gods.Size() != 0 && avl.size != 0 { + t.Error(src1) + t.Error(src2) + t.Error(avl.debugString()) + t.Error(gods.String()) + t.Error(l[i]) + // t.Error(avl.TraversalDepth(-1)) + // t.Error(gods.Values()) + break ALL + + } + } + } +} + +const CompartorSize = 300000 +const NumberMax = 60000000 + +func BenchmarkIterator(b *testing.B) { + avl := New(utils.IntComparator) + b.N = CompartorSize + + for i := 0; i < b.N; i++ { + v := randomdata.Number(0, NumberMax) + avl.Put(v) + } + + b.ResetTimer() + b.StartTimer() + iter := avl.Iterator() + for iter.Next() { + + } + + for iter.Prev() { + + } + + for iter.Next() { + + } + +} + +func BenchmarkGodsIterator(b *testing.B) { + avl := avltree.NewWithIntComparator() + b.N = CompartorSize + + for i := 0; i < b.N; i++ { + v := randomdata.Number(0, NumberMax) + avl.Put(v, i) + } + + b.ResetTimer() + b.StartTimer() + iter := avl.Iterator() + for iter.Next() { + + } + + for iter.Prev() { + + } + + for iter.Next() { + + } + +} + +func BenchmarkRemove(b *testing.B) { + + avl := New(utils.IntComparator) + b.N = CompartorSize + + var l []int + for i := 0; i < b.N; i++ { + v := randomdata.Number(0, NumberMax) + l = append(l, v) + avl.Put(v) + } + + b.ResetTimer() + b.StartTimer() + + for i := 0; i < b.N; i++ { + avl.Remove(l[i]) + } +} + +func BenchmarkGodsRemove(b *testing.B) { + avl := avltree.NewWithIntComparator() + b.N = CompartorSize + + var l []int + for i := 0; i < b.N; i++ { + v := randomdata.Number(0, NumberMax) + l = append(l, v) + avl.Put(v, v) + } + + b.ResetTimer() + b.StartTimer() + + for i := 0; i < b.N; i++ { + avl.Remove(l[i]) + } +} + +func BenchmarkGoGet(b *testing.B) { + avl := make(map[int]int) + + b.N = CompartorSize + for i := 0; i < b.N; i++ { + avl[randomdata.Number(0, NumberMax)] = i + } + + b.ResetTimer() + b.StartTimer() + b.N = CompartorSize + + var v int + var ok bool + for i := 0; i < b.N; i++ { + v, ok = avl[randomdata.Number(0, NumberMax)] + } + + if ok && v == 1 { + v = 1 + } +} + +func BenchmarkGet(b *testing.B) { + + avl := New(utils.IntComparator) + + b.N = CompartorSize + for i := 0; i < b.N/2; i++ { + avl.Put(randomdata.Number(0, NumberMax)) + } + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + avl.Get(randomdata.Number(0, NumberMax)) + } +} + +func BenchmarkGodsRBGet(b *testing.B) { + rb := redblacktree.NewWithIntComparator() + + b.N = CompartorSize + for i := 0; i < b.N/2; i++ { + rb.Put(randomdata.Number(0, NumberMax), i) + } + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + rb.Get(randomdata.Number(0, NumberMax)) + } +} + +func BenchmarkGodsAvlGet(b *testing.B) { + rb := avltree.NewWithIntComparator() + + b.N = CompartorSize + for i := 0; i < b.N/2; i++ { + rb.Put(randomdata.Number(0, NumberMax), i) + } + + b.ResetTimer() + b.StartTimer() + for i := 0; i < b.N; i++ { + rb.Get(randomdata.Number(0, NumberMax)) + } +} + +func BenchmarkGoPut(b *testing.B) { + avl := make(map[int]int) + + for i := 0; i < 100000; i++ { + avl[randomdata.Number(0, NumberMax)] = i + } + + b.ResetTimer() + b.StartTimer() + b.N = CompartorSize + + for i := 0; i < b.N; i++ { + avl[randomdata.Number(0, NumberMax)] = i + } + + log.Println(avl[12]) +} + +func BenchmarkGodsHashmap(b *testing.B) { + avl := hashmap.New() + + b.N = CompartorSize * 10 + for i := 0; i < b.N; i++ { + avl.Put(randomdata.Number(0, NumberMax), i) + } + + // b.ResetTimer() + // b.StartTimer() + // b.N = CompartorSize + + // for i := 0; i < b.N; i++ { + // avl[randomdata.Number(0, NumberMax)] = i + // } +} + +func BenchmarkPut(b *testing.B) { + avl := New(utils.IntComparator) + + for i := 0; i < 100000; i++ { + avl.Put(randomdata.Number(0, NumberMax)) + } + + b.ResetTimer() + b.StartTimer() + b.N = CompartorSize + for i := 0; i < b.N; i++ { + avl.Put(randomdata.Number(0, NumberMax)) + } + +} + +func BenchmarkGodsRBPut(b *testing.B) { + rb := redblacktree.NewWithIntComparator() + + for i := 0; i < 100000; i++ { + rb.Put(randomdata.Number(0, NumberMax), i) + } + + b.ResetTimer() + b.StartTimer() + + b.N = CompartorSize + for i := 0; i < b.N; i++ { + rb.Put(randomdata.Number(0, NumberMax), i) + } + +} + +func BenchmarkGodsPut(b *testing.B) { + avl := avltree.NewWithIntComparator() + + for i := 0; i < 100000; i++ { + avl.Put(randomdata.Number(0, NumberMax), i) + } + + b.ResetTimer() + b.StartTimer() + + b.N = CompartorSize + for i := 0; i < b.N; i++ { + avl.Put(randomdata.Number(0, NumberMax), i) + } +} diff --git a/avlkey/iterator.go b/avlkey/iterator.go new file mode 100644 index 0000000..65c9a31 --- /dev/null +++ b/avlkey/iterator.go @@ -0,0 +1,145 @@ +package avl + +import ( + "474420502.top/eson/structure/lastack" +) + +type Iterator struct { + op *AVL + + dir int + up *Node + cur *Node + tstack *lastack.Stack + // curnext *Node +} + +func initIterator(avltree *AVL) *Iterator { + iter := &Iterator{op: avltree, tstack: lastack.New()} + iter.up = avltree.root + return iter +} + +func (iter *Iterator) Value() interface{} { + return iter.cur.value +} + +func (iter *Iterator) Left() bool { + if iter.cur.children[0] != nil { + iter.dir = 0 + iter.cur = iter.cur.children[0] + return true + } + return false +} + +func (iter *Iterator) Right() bool { + if iter.cur.children[1] != nil { + iter.dir = 0 + iter.cur = iter.cur.children[1] + return true + } + return false +} + +func (iter *Iterator) Prev() (result bool) { + + if iter.dir > -1 { + if iter.dir == 1 && iter.cur != nil { + iter.tstack.Clear() + iter.curPushPrevStack(iter.cur) + iter.up = iter.getPrevUp(iter.cur) + } + iter.dir = -1 + } + + if iter.tstack.Size() == 0 { + if iter.up == nil { + return false + } + iter.tstack.Push(iter.up) + iter.up = iter.getPrevUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + iter.curPushPrevStack(iter.cur) + return true + } + + return false +} + +func (iter *Iterator) Next() (result bool) { + + if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev) + if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈 + iter.tstack.Clear() + iter.curPushNextStack(iter.cur) // 把当前cur计算的逆向回朔 + iter.up = iter.getNextUp(iter.cur) // cur 寻找下个要计算up + } + iter.dir = 1 + } + + // 如果栈空了, 把up的递归计算入栈, 重新计算 下次的up值 + if iter.tstack.Size() == 0 { + if iter.up == nil { + return false + } + iter.tstack.Push(iter.up) + iter.up = iter.getNextUp(iter.up) + } + + if v, ok := iter.tstack.Pop(); ok { + iter.cur = v.(*Node) + iter.curPushNextStack(iter.cur) + return true + } + + // 如果再次计算的栈为空, 则只能返回false + return false +} + +func (iter *Iterator) getNextUp(cur *Node) *Node { + for cur != nil { + if cur.child == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序 + return cur.parent + } + cur = cur.parent + } + return nil +} + +func (iter *Iterator) curPushNextStack(cur *Node) { + next := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值 + + if next != nil { + iter.tstack.Push(next) + for next.children[1] != nil { + next = next.children[1] + iter.tstack.Push(next) // 入栈 用于回溯 + } + } +} + +func (iter *Iterator) getPrevUp(cur *Node) *Node { + for cur != nil { + if cur.child == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序 + return cur.parent + } + cur = cur.parent + } + return nil +} + +func (iter *Iterator) curPushPrevStack(cur *Node) { + prev := cur.children[1] + + if prev != nil { + iter.tstack.Push(prev) + for prev.children[0] != nil { + prev = prev.children[0] + iter.tstack.Push(prev) + } + } +}