From 7be469782847a5c0985bca319731983b16cec7bf Mon Sep 17 00:00:00 2001 From: huangsimin Date: Thu, 14 Mar 2019 19:14:44 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E9=83=BD=E9=80=9A=E8=BF=87,?= =?UTF-8?q?=20=E5=AE=8C=E6=88=90avl=E6=A0=91=E7=9A=84=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=9E=B6=E6=9E=84.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- avl/avl.go | 330 +++++++++++------------- avl/avl_test.go | 487 ++++++++++++++++------------------- avl/iterator.go | 19 +- avldup/avldup.go | 345 +++++++++++++------------ avldup/avldup_test.go | 501 +++++++++++++++++++++++++----------- avldup/iterator.go | 19 +- avlkey/avlkey.go | 2 +- avlkey/avlkey_test.go | 2 +- avlkey/iterator.go | 2 +- avlkeydup/avlkeydup.go | 2 +- avlkeydup/avlkeydup_test.go | 2 +- avlkeydup/iterator.go | 2 +- 12 files changed, 933 insertions(+), 780 deletions(-) diff --git a/avl/avl.go b/avl/avl.go index 8852480..3422c11 100644 --- a/avl/avl.go +++ b/avl/avl.go @@ -10,17 +10,9 @@ type Node struct { children [2]*Node parent *Node height int - child int 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" @@ -30,40 +22,40 @@ func (n *Node) String() string { if n.parent != nil { p = spew.Sprint(n.parent.value) } - return spew.Sprint(n.value) + "(" + p + "-" + spew.Sprint(n.child) + "|" + spew.Sprint(n.height) + ")" + return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.height) + ")" } -type AVL struct { +type Tree struct { root *Node size int comparator utils.Comparator } -func New(comparator utils.Comparator) *AVL { - return &AVL{comparator: comparator} +func New(comparator utils.Comparator) *Tree { + return &Tree{comparator: comparator} } -func (avl *AVL) String() string { +func (avl *Tree) String() string { if avl.size == 0 { return "" } - str := "AVLTree" + "\n" + str := "AVLTree\n" output(avl.root, "", true, &str) return str } -func (avl *AVL) Iterator() *Iterator { +func (avl *Tree) Iterator() *Iterator { return initIterator(avl) } -func (avl *AVL) Size() int { +func (avl *Tree) Size() int { return avl.size } -func (avl *AVL) Remove(v interface{}) *Node { +func (avl *Tree) Remove(key interface{}) *Node { - if n, ok := avl.GetNode(v); ok { + if n, ok := avl.GetNode(key); ok { avl.size-- if avl.size == 0 { @@ -76,7 +68,7 @@ func (avl *AVL) Remove(v interface{}) *Node { if left == -1 && right == -1 { p := n.parent - p.children[n.child] = nil + p.children[getRelationship(n)] = nil avl.fixRemoveHeight(p) return n } @@ -89,9 +81,8 @@ func (avl *AVL) Remove(v interface{}) *Node { } cleft := cur.children[0] - cur.parent.children[cur.child] = cleft + cur.parent.children[getRelationship(cur)] = cleft if cleft != nil { - cleft.child = cur.child cleft.parent = cur.parent } @@ -102,47 +93,49 @@ func (avl *AVL) Remove(v interface{}) *Node { } cright := cur.children[1] - cur.parent.children[cur.child] = cright + cur.parent.children[getRelationship(cur)] = cright + if cright != nil { - cright.child = cur.child cright.parent = cur.parent } } cparent := cur.parent - avl.replace(n, cur) + // 修改为interface 交换 + n.value, cur.value = cur.value, n.value + // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 if cparent == n { - avl.fixRemoveHeight(cur) + avl.fixRemoveHeight(n) } else { avl.fixRemoveHeight(cparent) } - return n + return cur } return nil } -func (avl *AVL) Get(v interface{}) (interface{}, bool) { - n, ok := avl.GetNode(v) +func (avl *Tree) Get(key interface{}) (interface{}, bool) { + n, ok := avl.GetNode(key) if ok { return n.value, true } return n, false } -func (avl *AVL) GetAround(v interface{}) (result [3]interface{}) { - an := avl.GetAroundNode(v) +func (avl *Tree) GetAround(key interface{}) (result [3]interface{}) { + an := avl.GetAroundNode(key) for i, n := range an { - if n.value != nil { + if n != nil { result[i] = n.value } } return } -func (avl *AVL) GetAroundNode(v interface{}) (result [3]*Node) { +func (avl *Tree) GetAroundNode(value interface{}) (result [3]*Node) { n := avl.root for { @@ -152,7 +145,7 @@ func (avl *AVL) GetAroundNode(v interface{}) (result [3]*Node) { } lastc := 0 - switch c := avl.comparator(v, n.value); c { + switch c := avl.comparator(value, n.value); c { case -1: if c != -lastc { result[0] = n @@ -195,11 +188,10 @@ func (avl *AVL) GetAroundNode(v interface{}) (result [3]*Node) { } } -func (avl *AVL) GetNode(v interface{}) (*Node, bool) { +func (avl *Tree) GetNode(value interface{}) (*Node, bool) { - n := avl.root - for n != nil { - switch c := avl.comparator(v, n.value); c { + for n := avl.root; n != nil; { + switch c := avl.comparator(value, n.value); c { case -1: n = n.children[0] case 1: @@ -210,13 +202,12 @@ func (avl *AVL) GetNode(v interface{}) (*Node, bool) { panic("Get comparator only is allowed in -1, 0, 1") } } - return nil, false } -func (avl *AVL) Put(v interface{}) { +func (avl *Tree) Put(value interface{}) { avl.size++ - node := &Node{value: v} + node := &Node{value: value} if avl.size == 1 { avl.root = node return @@ -231,8 +222,6 @@ func (avl *AVL) Put(v interface{}) { if cur == nil { parent.children[child] = node node.parent = parent - node.child = child - if node.parent.height == 0 { avl.fixPutHeight(node.parent) } @@ -240,65 +229,23 @@ func (avl *AVL) Put(v interface{}) { } parent = cur - c := avl.comparator(node.value, cur.value) - 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 + c := avl.comparator(value, cur.value) + child = (c + 2) / 2 + cur = cur.children[child] } } -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 { +func (avl *Tree) debugString() string { if avl.size == 0 { return "" } - str := "AVL" + "\n" + str := "AVLTree\n" outputfordebug(avl.root, "", true, &str) return str } -func (avl *AVL) TraversalBreadth() (result []interface{}) { +func (avl *Tree) TraversalBreadth() (result []interface{}) { + result = make([]interface{}, 0, avl.size) var traverasl func(cur *Node) traverasl = func(cur *Node) { if cur == nil { @@ -312,8 +259,8 @@ func (avl *AVL) TraversalBreadth() (result []interface{}) { return } -func (avl *AVL) TraversalDepth(leftright int) (result []interface{}) { - +func (avl *Tree) TraversalDepth(leftright int) (result []interface{}) { + result = make([]interface{}, 0, avl.size) if leftright < 0 { var traverasl func(cur *Node) traverasl = func(cur *Node) { @@ -341,111 +288,148 @@ func (avl *AVL) TraversalDepth(leftright int) (result []interface{}) { return } -func (avl *AVL) lrrotate(cur *Node) *Node { +func (avl *Tree) lrrotate(cur *Node) { - r := cur.children[1] - rl := r.children[0] - if cur.parent == nil { - avl.root = rl - rl.parent = nil + 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 { - setChildNotNil(cur.parent, cur.child, rl) + movparent.children[r] = nil } - rll := rl.children[0] - rlr := rl.children[1] + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + //mov.children[l].child = l + } else { + mov.children[l] = nil + } - setChild(cur, 1, rll) - setChild(r, 0, rlr) + if cur.children[r] != nil { + mov.children[r] = cur.children[r] + mov.children[r].parent = mov + } else { + mov.children[r] = nil + } - setChildNotNil(rl, 0, cur) - setChildNotNil(rl, 1, r) + cur.children[r] = mov + mov.parent = cur + mov.height = getMaxChildrenHeight(mov) + 1 + movparent.height = getMaxChildrenHeight(movparent) + 1 cur.height = getMaxChildrenHeight(cur) + 1 - r.height = getMaxChildrenHeight(r) + 1 - rl.height = getMaxChildrenHeight(rl) + 1 - - return rl } -func (avl *AVL) rlrotate(cur *Node) *Node { +func (avl *Tree) rlrotate(cur *Node) { - l := cur.children[0] - lr := l.children[1] - if cur.parent == nil { - avl.root = lr - lr.parent = nil + 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 { - setChildNotNil(cur.parent, cur.child, lr) + movparent.children[r] = nil } - lrr := lr.children[1] - lrl := lr.children[0] + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + } else { + mov.children[l] = nil + } - setChild(cur, 0, lrr) - setChild(l, 1, lrl) - setChildNotNil(lr, 1, cur) - setChildNotNil(lr, 0, l) + 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 + + mov.height = getMaxChildrenHeight(mov) + 1 + movparent.height = getMaxChildrenHeight(movparent) + 1 cur.height = getMaxChildrenHeight(cur) + 1 - l.height = getMaxChildrenHeight(l) + 1 - lr.height = getMaxChildrenHeight(lr) + 1 - - return lr } -func (avl *AVL) rrotate(cur *Node) *Node { +func (avl *Tree) rrotate(cur *Node) { - l := cur.children[0] + const l = 0 + const r = 1 + // 1 right 0 left + mov := cur.children[l] - setChild(cur, 0, l.children[1]) + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 - l.parent = cur.parent - if cur.parent == nil { - avl.root = l + // 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 { - cur.parent.children[cur.child] = l + mov.children[l] = nil } - l.child = cur.child - setChildNotNil(l, 1, cur) - // l.children[1] = cur - // cur.child = 1 - // cur.parent = l + 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.height = getMaxChildrenHeight(mov) + 1 cur.height = getMaxChildrenHeight(cur) + 1 - l.height = getMaxChildrenHeight(l) + 1 - - return l // 返回前 替换为cur节点的节点, 有利余修复高度 } -func (avl *AVL) lrotate(cur *Node) *Node { +func (avl *Tree) lrotate(cur *Node) { - r := cur.children[1] + const l = 1 + const r = 0 - // 右左节点 链接 当前的右节点 - setChild(cur, 1, r.children[0]) + mov := cur.children[l] - // 设置 需要旋转的节点到当前节点的 链条 - r.parent = cur.parent - if cur.parent == nil { - avl.root = r + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + // 不可能为nil + mov.children[l].parent = cur + cur.children[l] = mov.children[l] + + if mov.children[r] != nil { + mov.children[l] = mov.children[r] } else { - cur.parent.children[cur.child] = r + mov.children[l] = nil } - r.child = cur.child - // 当前节点旋转到 左边的 链条 - setChildNotNil(r, 0, cur) - // r.children[0] = cur - // cur.child = 0 - // cur.parent = r + 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.height = getMaxChildrenHeight(mov) + 1 cur.height = getMaxChildrenHeight(cur) + 1 - r.height = getMaxChildrenHeight(r) + 1 - - return r } func getMaxAndChildrenHeight(cur *Node) (h1, h2, maxh int) { @@ -476,7 +460,7 @@ func getHeight(cur *Node) int { return cur.height } -func (avl *AVL) fixRemoveHeight(cur *Node) { +func (avl *Tree) fixRemoveHeight(cur *Node) { for { @@ -495,16 +479,16 @@ func (avl *AVL) fixRemoveHeight(cur *Node) { if diff < -1 { r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 if getHeight(r.children[0]) > getHeight(r.children[1]) { - cur = avl.lrrotate(cur) + avl.lrrotate(cur) } else { - cur = avl.lrotate(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) + avl.rlrotate(cur) } else { - cur = avl.rrotate(cur) + avl.rrotate(cur) } } else { @@ -523,7 +507,7 @@ func (avl *AVL) fixRemoveHeight(cur *Node) { } -func (avl *AVL) fixPutHeight(cur *Node) { +func (avl *Tree) fixPutHeight(cur *Node) { for { @@ -535,18 +519,18 @@ func (avl *AVL) fixPutHeight(cur *Node) { if diff < -1 { r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 if getHeight(r.children[0]) > getHeight(r.children[1]) { - cur = avl.lrrotate(cur) + avl.lrrotate(cur) } else { - cur = avl.lrotate(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) + avl.rlrotate(cur) } else { - cur = avl.rrotate(cur) + avl.rrotate(cur) } + } else { // 选择一个child的最大高度 + 1为 高度 if lefth > rigthh { @@ -620,7 +604,7 @@ func outputfordebug(node *Node, prefix string, isTail bool, str *string) { } else { parentv = spew.Sprint(node.parent.value) } - suffix += parentv + "-" + spew.Sprint(node.child) + "|" + spew.Sprint(node.height) + ")" + suffix += parentv + "|" + spew.Sprint(node.height) + ")" *str += spew.Sprint(node.value) + suffix + "\n" if node.children[0] != nil { diff --git a/avl/avl_test.go b/avl/avl_test.go index 6cc2757..7d6013b 100644 --- a/avl/avl_test.go +++ b/avl/avl_test.go @@ -1,44 +1,60 @@ package avl import ( + "bytes" + "encoding/gob" + "io/ioutil" "log" + "os" "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/davecgh/go-spew/spew" + "github.com/emirpasic/gods/trees/avltree" + "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" ) -func TestRotate(t *testing.T) { - avl := New(utils.IntComparator) +const CompartorSize = 500000 +const NumberMax = 60000000 - content := "" - for i := 0; i < 10; i++ { - v := randomdata.Number(0, 1000) - content += spew.Sprint(v) + " " - avl.Put(v) +func TestSave(t *testing.T) { + + f, err := os.OpenFile("../l.log", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) + if err != nil { + log.Println(err) } - t.Error(content) - src := avl.String() - t.Error(src) + //fmt.Println(userBytes) - lsrc := avl.String() - t.Error(lsrc) - // rrotate(&avl.root) - rsrc := avl.String() - t.Error(rsrc) - - if src == rsrc { - t.Error("src == rsrc") + var l []int + m := make(map[int]int) + for i := 0; len(l) < CompartorSize; i++ { + v := randomdata.Number(0, NumberMax) + if _, ok := m[v]; !ok { + m[v] = v + l = append(l, v) + } } + + var result bytes.Buffer + encoder := gob.NewEncoder(&result) + encoder.Encode(l) + lbytes := result.Bytes() + f.Write(lbytes) + +} + +func loadTestData() []int { + data, err := ioutil.ReadFile("../l.log") + if err != nil { + log.Println(err) + } + var l []int + decoder := gob.NewDecoder(bytes.NewReader(data)) + decoder.Decode(&l) + return l } func TestIterator(t *testing.T) { @@ -48,88 +64,92 @@ func TestIterator(t *testing.T) { avl.Put(v) } - t.Error(avl.TraversalDepth(1)) - t.Error(avl.debugString()) - iter := avl.Iterator() + // ` AVLTree + // │ ┌── 30 + // │ │ └── 21 + // │ ┌── 20 + // │ │ └── 15 + // └── 14 + // │ ┌── 7 + // │ ┌── 7 + // │ │ └── 6 + // └── 5 + // │ ┌── 4 + // │ │ └── 3 + // └── 2 + // └── 1` - for iter.Prev() { - t.Error(iter.Value()) - } - t.Error("prev == false", iter.Value(), iter.Prev(), iter.Value()) + iter := avl.Iterator() // root start point - for iter.Next() { - t.Error(iter.Value()) - } - t.Error("next == false", iter.Value(), iter.Next(), iter.Value()) + l := []int{14, 15, 20, 21, 30} - 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 + for i := 0; iter.Prev(); i++ { + if iter.Value().(int) != l[i] { + t.Error("iter prev error", iter.Value(), l[i]) } } - t.Error("next == false", iter.Value()) - for iter.Prev() { - t.Error(iter.Value()) + iter.Prev() + if iter.Value().(int) != 30 { + t.Error("prev == false", iter.Value(), iter.Prev(), iter.Value()) + } + + l = []int{21, 20, 15, 14, 7, 7, 6, 5, 4, 3, 2, 1} + for i := 0; iter.Next(); i++ { // cur is 30 next is 21 + if iter.Value().(int) != l[i] { + t.Error(iter.Value()) + } + } + + if iter.Next() != false { + t.Error("Next is error, cur is tail, val = 1 Next return false") + } + if iter.Value().(int) != 1 { // cur is 1 + t.Error("next == false", iter.Value(), iter.Next(), iter.Value()) + } + + if iter.Prev() != true && iter.Value().(int) != 2 { + t.Error("next to prev is error") } - 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)) + + if spew.Sprint(avl.GetAround(30)) != "[40 30 21]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(30))) + } + + if spew.Sprint(avl.GetAround(40)) != "[40 40 30]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(50))) + } + + if spew.Sprint(avl.GetAround(50)) != "[ 50 40]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(50))) + } } +// for test error case 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()) + // avl := New(utils.IntComparator) + // gods := avltree.NewWithIntComparator() + // // 44908, 34985, 62991, 4201, 27210, 30707 + // for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + // t.Error(v) + // t.Error(avl.debugString()) + // avl.Put(v,) + // gods.Put(v, v) + // t.Error(avl.debugString()) + // t.Error(gods.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++ { + for n := 0; n < 300000; n++ { avl := New(utils.IntComparator) godsavl := avltree.NewWithIntComparator() @@ -139,82 +159,95 @@ func TestPutComparatorRandom(t *testing.T) { v := randomdata.Number(0, 65535) if _, ok := m[v]; !ok { m[v] = v - content += spew.Sprint(v) + " " - // t.Error(v) + content += spew.Sprint(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(avl.debugString()) 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)) + for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + avl.Put(v) } - t.Error(avl.String()) - t.Error(avl.Get(500)) + + result := ` +│ ┌── 57092 +│ ┌── 39016 +│ │ └── 36513 +│ ┌── 27897 +│ │ │ ┌── 23202 +│ │ └── 22574 +└── 7666 + │ ┌── 3055 + └── 2383 + └── 1562 +` + + s1 := avl.String() + s2 := "AVLTree" + result + if s1 != s2 { + t.Error(s1, s2) + } + + for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + v, ok := avl.Get(v) + if !ok { + t.Error("the val not found ", v) + } + } + + if v, ok := avl.Get(10000); ok { + t.Error("the val(1000) is not in tree, but is found", v) + } + } 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) - +ALL: + for c := 0; c < 5000; c++ { avl := New(utils.IntComparator) + gods := avltree.NewWithIntComparator() var l []int - for i := 0; i < 100; i++ { + m := make(map[int]int) + + for i := 0; len(l) < 100; i++ { v := randomdata.Number(0, 100000) - l = append(l, v) - avl.Put(v) + if _, ok := m[v]; !ok { + m[v] = v + l = append(l, v) + avl.Put(v) + gods.Put(v, 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]) + gods.Remove(l[i]) + s1 := spew.Sprint(avl.TraversalDepth(-1)) + s2 := spew.Sprint(gods.Values()) + if s1 != s2 { + t.Error("avl remove error", "avlsize = ", avl.Size()) + t.Error(s1) + t.Error(s2) + break ALL + } } } } 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) @@ -249,126 +282,105 @@ ALL: // 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 + tree := New(utils.IntComparator) - for i := 0; i < b.N; i++ { - v := randomdata.Number(0, NumberMax) - avl.Put(v) + l := loadTestData() + b.N = len(l) + + for _, v := range l { + tree.Put(v) } b.ResetTimer() b.StartTimer() - iter := avl.Iterator() + iter := tree.Iterator() for iter.Next() { - } - for iter.Prev() { - } - for iter.Next() { - } } func BenchmarkGodsIterator(b *testing.B) { - avl := avltree.NewWithIntComparator() - b.N = CompartorSize + tree := avltree.NewWithIntComparator() - for i := 0; i < b.N; i++ { - v := randomdata.Number(0, NumberMax) - avl.Put(v, i) + l := loadTestData() + b.N = len(l) + + for _, v := range l { + tree.Put(v, v) } b.ResetTimer() b.StartTimer() - iter := avl.Iterator() + iter := tree.Iterator() for iter.Next() { - } - for iter.Prev() { - } - for iter.Next() { - } - } func BenchmarkRemove(b *testing.B) { + tree := New(utils.IntComparator) - avl := New(utils.IntComparator) - b.N = CompartorSize + l := loadTestData() - var l []int - for i := 0; i < b.N; i++ { - v := randomdata.Number(0, NumberMax) - l = append(l, v) - avl.Put(v) + b.N = len(l) + for _, v := range l { + tree.Put(v) } b.ResetTimer() b.StartTimer() - for i := 0; i < b.N; i++ { - avl.Remove(l[i]) + for i := 0; i < len(l); i++ { + tree.Remove(l[i]) } } func BenchmarkGodsRemove(b *testing.B) { - avl := avltree.NewWithIntComparator() - b.N = CompartorSize + tree := avltree.NewWithIntComparator() - var l []int - for i := 0; i < b.N; i++ { - v := randomdata.Number(0, NumberMax) - l = append(l, v) - avl.Put(v, v) + l := loadTestData() + + b.N = len(l) + for _, v := range l { + tree.Put(v, v) } b.ResetTimer() b.StartTimer() - for i := 0; i < b.N; i++ { - avl.Remove(l[i]) + for i := 0; i < len(l); i++ { + tree.Remove(l[i]) } } -func BenchmarkGoGet(b *testing.B) { - avl := make(map[int]int) +func BenchmarkGodsRBRemove(b *testing.B) { + tree := redblacktree.NewWithIntComparator() - b.N = CompartorSize - for i := 0; i < b.N; i++ { - avl[randomdata.Number(0, NumberMax)] = i + l := loadTestData() + + b.N = len(l) + for _, v := range l { + tree.Put(v, v) } 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 + for i := 0; i < len(l); i++ { + tree.Remove(l[i]) } } @@ -376,128 +388,81 @@ 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)) - } + l := loadTestData() + b.N = len(l) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { - avl.Get(randomdata.Number(0, NumberMax)) + avl.Get(l[i]) } } func BenchmarkGodsRBGet(b *testing.B) { - rb := redblacktree.NewWithIntComparator() + tree := redblacktree.NewWithIntComparator() - b.N = CompartorSize - for i := 0; i < b.N/2; i++ { - rb.Put(randomdata.Number(0, NumberMax), i) - } + l := loadTestData() + b.N = len(l) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { - rb.Get(randomdata.Number(0, NumberMax)) + tree.Get(l[i]) } } func BenchmarkGodsAvlGet(b *testing.B) { - rb := avltree.NewWithIntComparator() + tree := avltree.NewWithIntComparator() - b.N = CompartorSize - for i := 0; i < b.N/2; i++ { - rb.Put(randomdata.Number(0, NumberMax), i) - } + l := loadTestData() + b.N = len(l) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { - rb.Get(randomdata.Number(0, NumberMax)) + tree.Get(l[i]) } } -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)) - } + l := loadTestData() b.ResetTimer() b.StartTimer() - b.N = CompartorSize - for i := 0; i < b.N; i++ { - avl.Put(randomdata.Number(0, NumberMax)) + + b.N = len(l) + for _, v := range l { + avl.Put(v) } } func BenchmarkGodsRBPut(b *testing.B) { - rb := redblacktree.NewWithIntComparator() + tree := redblacktree.NewWithIntComparator() - for i := 0; i < 100000; i++ { - rb.Put(randomdata.Number(0, NumberMax), i) - } + l := loadTestData() b.ResetTimer() b.StartTimer() - b.N = CompartorSize - for i := 0; i < b.N; i++ { - rb.Put(randomdata.Number(0, NumberMax), i) + b.N = len(l) + for _, v := range l { + tree.Put(v, v) } - } func BenchmarkGodsPut(b *testing.B) { - avl := avltree.NewWithIntComparator() + tree := avltree.NewWithIntComparator() - for i := 0; i < 100000; i++ { - avl.Put(randomdata.Number(0, NumberMax), i) - } + l := loadTestData() b.ResetTimer() b.StartTimer() - b.N = CompartorSize - for i := 0; i < b.N; i++ { - avl.Put(randomdata.Number(0, NumberMax), i) + b.N = len(l) + for _, v := range l { + tree.Put(v, v) } } diff --git a/avl/iterator.go b/avl/iterator.go index 65c9a31..3ca4567 100644 --- a/avl/iterator.go +++ b/avl/iterator.go @@ -5,7 +5,7 @@ import ( ) type Iterator struct { - op *AVL + op *Tree dir int up *Node @@ -14,7 +14,7 @@ type Iterator struct { // curnext *Node } -func initIterator(avltree *AVL) *Iterator { +func initIterator(avltree *Tree) *Iterator { iter := &Iterator{op: avltree, tstack: lastack.New()} iter.up = avltree.root return iter @@ -100,9 +100,16 @@ func (iter *Iterator) Next() (result bool) { return false } +func getRelationship(cur *Node) int { + if cur.parent.children[1] == cur { + return 1 + } + return 0 +} + func (iter *Iterator) getNextUp(cur *Node) *Node { - for cur != nil { - if cur.child == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序 + for cur.parent != nil { + if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序 return cur.parent } cur = cur.parent @@ -123,8 +130,8 @@ func (iter *Iterator) curPushNextStack(cur *Node) { } func (iter *Iterator) getPrevUp(cur *Node) *Node { - for cur != nil { - if cur.child == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序 + for cur.parent != nil { + if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序 return cur.parent } cur = cur.parent diff --git a/avldup/avldup.go b/avldup/avldup.go index a068bae..eb29a08 100644 --- a/avldup/avldup.go +++ b/avldup/avldup.go @@ -10,7 +10,6 @@ type Node struct { children [2]*Node parent *Node height int - child int value interface{} } @@ -30,40 +29,40 @@ func (n *Node) String() string { if n.parent != nil { p = spew.Sprint(n.parent.value) } - return spew.Sprint(n.value) + "(" + p + "-" + spew.Sprint(n.child) + "|" + spew.Sprint(n.height) + ")" + return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.height) + ")" } -type AVLDup struct { +type Tree struct { root *Node size int comparator utils.Comparator } -func New(comparator utils.Comparator) *AVLDup { - return &AVLDup{comparator: comparator} +func New(comparator utils.Comparator) *Tree { + return &Tree{comparator: comparator} } -func (avl *AVLDup) String() string { +func (avl *Tree) String() string { if avl.size == 0 { return "" } - str := "AVLTree" + "\n" + str := "AVLTree\n" output(avl.root, "", true, &str) return str } -func (avl *AVLDup) Iterator() *Iterator { +func (avl *Tree) Iterator() *Iterator { return initIterator(avl) } -func (avl *AVLDup) Size() int { +func (avl *Tree) Size() int { return avl.size } -func (avl *AVLDup) Remove(v interface{}) *Node { +func (avl *Tree) Remove(value interface{}) *Node { - if n, ok := avl.GetNode(v); ok { + if n, ok := avl.GetNode(value); ok { avl.size-- if avl.size == 0 { @@ -76,7 +75,7 @@ func (avl *AVLDup) Remove(v interface{}) *Node { if left == -1 && right == -1 { p := n.parent - p.children[n.child] = nil + p.children[getRelationship(n)] = nil avl.fixRemoveHeight(p) return n } @@ -89,9 +88,8 @@ func (avl *AVLDup) Remove(v interface{}) *Node { } cleft := cur.children[0] - cur.parent.children[cur.child] = cleft + cur.parent.children[getRelationship(cur)] = cleft if cleft != nil { - cleft.child = cur.child cleft.parent = cur.parent } @@ -102,46 +100,49 @@ func (avl *AVLDup) Remove(v interface{}) *Node { } cright := cur.children[1] - cur.parent.children[cur.child] = cright + cur.parent.children[getRelationship(cur)] = cright + if cright != nil { - cright.child = cur.child cright.parent = cur.parent } } cparent := cur.parent - avl.replace(n, cur) + // 修改为interface 交换 + n.value, cur.value = cur.value, n.value + // 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度 if cparent == n { - avl.fixRemoveHeight(cur) + avl.fixRemoveHeight(n) } else { avl.fixRemoveHeight(cparent) } - return n + return cur } + return nil } -func (avl *AVLDup) Get(v interface{}) (interface{}, bool) { - n, ok := avl.GetNode(v) +func (avl *Tree) Get(key interface{}) (interface{}, bool) { + n, ok := avl.GetNode(key) if ok { return n.value, true } return n, false } -func (avl *AVLDup) GetAround(v interface{}) (result [3]interface{}) { - an := avl.GetAroundNode(v) +func (avl *Tree) GetAround(key interface{}) (result [3]interface{}) { + an := avl.GetAroundNode(key) for i, n := range an { - if n.value != nil { + if n != nil { result[i] = n.value } } return } -func (avl *AVLDup) GetAroundNode(v interface{}) (result [3]*Node) { +func (avl *Tree) GetAroundNode(value interface{}) (result [3]*Node) { n := avl.root for { @@ -151,7 +152,7 @@ func (avl *AVLDup) GetAroundNode(v interface{}) (result [3]*Node) { } lastc := 0 - switch c := avl.comparator(v, n.value); c { + switch c := avl.comparator(value, n.value); c { case -1: if c != -lastc { result[0] = n @@ -194,11 +195,10 @@ func (avl *AVLDup) GetAroundNode(v interface{}) (result [3]*Node) { } } -func (avl *AVLDup) GetNode(v interface{}) (*Node, bool) { +func (avl *Tree) GetNode(value interface{}) (*Node, bool) { - n := avl.root - for n != nil { - switch c := avl.comparator(v, n.value); c { + for n := avl.root; n != nil; { + switch c := avl.comparator(value, n.value); c { case -1: n = n.children[0] case 1: @@ -209,14 +209,13 @@ func (avl *AVLDup) GetNode(v interface{}) (*Node, bool) { panic("Get comparator only is allowed in -1, 0, 1") } } - return nil, false } -func (avl *AVLDup) Put(v interface{}) { +func (avl *Tree) Put(value interface{}) { if avl.size == 0 { - avl.root = &Node{value: v} + avl.root = &Node{value: value} avl.size++ return } @@ -228,12 +227,10 @@ func (avl *AVLDup) Put(v interface{}) { for { if cur == nil { - node := &Node{value: v} + avl.size++ + node := &Node{value: value} parent.children[child] = node node.parent = parent - node.child = child - avl.size++ - if node.parent.height == 0 { avl.fixPutHeight(node.parent) } @@ -241,69 +238,24 @@ func (avl *AVLDup) Put(v interface{}) { } parent = cur - c := avl.comparator(v, cur.value) - switch c { // right - case 1: - child = 1 - cur = cur.children[child] - case -1: - child = 0 - cur = cur.children[child] - case 0: - cur.value = v - return - } + c := avl.comparator(value, cur.value) + child = (c + 2) / 2 + cur = cur.children[child] } } -func (avl *AVLDup) 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 *AVLDup) debugString() string { +func (avl *Tree) debugString() string { if avl.size == 0 { return "" } - str := "AVLDup" + "\n" + str := "AVLTree\n" outputfordebug(avl.root, "", true, &str) return str } -func (avl *AVLDup) TraversalBreadth() (result []interface{}) { +func (avl *Tree) TraversalBreadth() (result []interface{}) { + result = make([]interface{}, 0, avl.size) var traverasl func(cur *Node) traverasl = func(cur *Node) { if cur == nil { @@ -317,8 +269,8 @@ func (avl *AVLDup) TraversalBreadth() (result []interface{}) { return } -func (avl *AVLDup) TraversalDepth(leftright int) (result []interface{}) { - +func (avl *Tree) TraversalDepth(leftright int) (result []interface{}) { + result = make([]interface{}, 0, avl.size) if leftright < 0 { var traverasl func(cur *Node) traverasl = func(cur *Node) { @@ -346,111 +298,162 @@ func (avl *AVLDup) TraversalDepth(leftright int) (result []interface{}) { return } -func (avl *AVLDup) lrrotate(cur *Node) *Node { +func (avl *Tree) lrrotate(cur *Node) { - r := cur.children[1] - rl := r.children[0] - if cur.parent == nil { - avl.root = rl - rl.parent = nil + 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 { - setChildNotNil(cur.parent, cur.child, rl) + movparent.children[r] = nil } - rll := rl.children[0] - rlr := rl.children[1] + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + //mov.children[l].child = l + } else { + mov.children[l] = nil + } - setChild(cur, 1, rll) - setChild(r, 0, rlr) + if cur.children[r] != nil { + mov.children[r] = cur.children[r] + mov.children[r].parent = mov + } else { + mov.children[r] = nil + } - setChildNotNil(rl, 0, cur) - setChildNotNil(rl, 1, r) + cur.children[r] = mov + mov.parent = cur + mov.height = getMaxChildrenHeight(mov) + 1 + movparent.height = getMaxChildrenHeight(movparent) + 1 cur.height = getMaxChildrenHeight(cur) + 1 - r.height = getMaxChildrenHeight(r) + 1 - rl.height = getMaxChildrenHeight(rl) + 1 - - return rl } -func (avl *AVLDup) rlrotate(cur *Node) *Node { +func (avl *Tree) rlrotate(cur *Node) { - l := cur.children[0] - lr := l.children[1] - if cur.parent == nil { - avl.root = lr - lr.parent = nil + 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 { - setChildNotNil(cur.parent, cur.child, lr) + movparent.children[r] = nil } - lrr := lr.children[1] - lrl := lr.children[0] + if mov.children[r] != nil { + mov.children[l] = mov.children[r] + } else { + mov.children[l] = nil + } - setChild(cur, 0, lrr) - setChild(l, 1, lrl) - setChildNotNil(lr, 1, cur) - setChildNotNil(lr, 0, l) + 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 + + mov.height = getMaxChildrenHeight(mov) + 1 + movparent.height = getMaxChildrenHeight(movparent) + 1 cur.height = getMaxChildrenHeight(cur) + 1 - l.height = getMaxChildrenHeight(l) + 1 - lr.height = getMaxChildrenHeight(lr) + 1 - - return lr } -func (avl *AVLDup) rrotate(cur *Node) *Node { +func (avl *Tree) rrotate(cur *Node) { - l := cur.children[0] + const l = 0 + const r = 1 + // 1 right 0 left + mov := cur.children[l] - setChild(cur, 0, l.children[1]) + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 - l.parent = cur.parent - if cur.parent == nil { - avl.root = l + // if mov.children[l] != nil { + // mov.children[l].parent = cur + // cur.children[l] = mov.children[l] + // } else { + // cur.children[l] = nil + // } + + // 不可能为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 { - cur.parent.children[cur.child] = l + mov.children[l] = nil } - l.child = cur.child - setChildNotNil(l, 1, cur) - // l.children[1] = cur - // cur.child = 1 - // cur.parent = l + 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.height = getMaxChildrenHeight(mov) + 1 cur.height = getMaxChildrenHeight(cur) + 1 - l.height = getMaxChildrenHeight(l) + 1 - - return l // 返回前 替换为cur节点的节点, 有利余修复高度 } -func (avl *AVLDup) lrotate(cur *Node) *Node { +func (avl *Tree) lrotate(cur *Node) { - r := cur.children[1] + const l = 1 + const r = 0 - // 右左节点 链接 当前的右节点 - setChild(cur, 1, r.children[0]) + mov := cur.children[l] - // 设置 需要旋转的节点到当前节点的 链条 - r.parent = cur.parent - if cur.parent == nil { - avl.root = r + mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移 + + // if mov.children[l] != nil { + // mov.children[l].parent = cur + // cur.children[l] = mov.children[l] + // } else { + // cur.children[l] = nil + // } + + // 不可能为nil + mov.children[l].parent = cur + cur.children[l] = mov.children[l] + + if mov.children[r] != nil { + mov.children[l] = mov.children[r] } else { - cur.parent.children[cur.child] = r + mov.children[l] = nil } - r.child = cur.child - // 当前节点旋转到 左边的 链条 - setChildNotNil(r, 0, cur) - // r.children[0] = cur - // cur.child = 0 - // cur.parent = r + 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.height = getMaxChildrenHeight(mov) + 1 cur.height = getMaxChildrenHeight(cur) + 1 - r.height = getMaxChildrenHeight(r) + 1 - - return r } func getMaxAndChildrenHeight(cur *Node) (h1, h2, maxh int) { @@ -481,7 +484,7 @@ func getHeight(cur *Node) int { return cur.height } -func (avl *AVLDup) fixRemoveHeight(cur *Node) { +func (avl *Tree) fixRemoveHeight(cur *Node) { for { @@ -500,16 +503,16 @@ func (avl *AVLDup) fixRemoveHeight(cur *Node) { if diff < -1 { r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 if getHeight(r.children[0]) > getHeight(r.children[1]) { - cur = avl.lrrotate(cur) + avl.lrrotate(cur) } else { - cur = avl.lrotate(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) + avl.rlrotate(cur) } else { - cur = avl.rrotate(cur) + avl.rrotate(cur) } } else { @@ -528,7 +531,7 @@ func (avl *AVLDup) fixRemoveHeight(cur *Node) { } -func (avl *AVLDup) fixPutHeight(cur *Node) { +func (avl *Tree) fixPutHeight(cur *Node) { for { @@ -540,18 +543,18 @@ func (avl *AVLDup) fixPutHeight(cur *Node) { if diff < -1 { r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式 if getHeight(r.children[0]) > getHeight(r.children[1]) { - cur = avl.lrrotate(cur) + avl.lrrotate(cur) } else { - cur = avl.lrotate(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) + avl.rlrotate(cur) } else { - cur = avl.rrotate(cur) + avl.rrotate(cur) } + } else { // 选择一个child的最大高度 + 1为 高度 if lefth > rigthh { @@ -625,7 +628,7 @@ func outputfordebug(node *Node, prefix string, isTail bool, str *string) { } else { parentv = spew.Sprint(node.parent.value) } - suffix += parentv + "-" + spew.Sprint(node.child) + "|" + spew.Sprint(node.height) + ")" + suffix += parentv + "|" + spew.Sprint(node.height) + ")" *str += spew.Sprint(node.value) + suffix + "\n" if node.children[0] != nil { diff --git a/avldup/avldup_test.go b/avldup/avldup_test.go index d37c42d..51c404c 100644 --- a/avldup/avldup_test.go +++ b/avldup/avldup_test.go @@ -1,173 +1,297 @@ package avldup import ( + "bytes" + "encoding/gob" + "io/ioutil" + "log" + "os" "testing" - "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/davecgh/go-spew/spew" + "github.com/emirpasic/gods/trees/avltree" + "github.com/emirpasic/gods/trees/redblacktree" "github.com/emirpasic/gods/utils" ) -func TestRotate(t *testing.T) { - avl := New(utils.IntComparator) +const CompartorSize = 500000 +const NumberMax = 60000000 - content := "" - for i := 0; i < 10; i++ { - v := randomdata.Number(0, 1000) - content += spew.Sprint(v) + " " - avl.Put(v) +func TestSave(t *testing.T) { + + f, err := os.OpenFile("../l.log", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666) + if err != nil { + log.Println(err) } - t.Error(content) - src := avl.String() - t.Error(src) + //fmt.Println(userBytes) - lsrc := avl.String() - t.Error(lsrc) - // rrotate(&avl.root) - rsrc := avl.String() - t.Error(rsrc) - - if src == rsrc { - t.Error("src == rsrc") - } -} - -func TestPutStable(t *testing.T) { - avl := New(utils.IntComparator) - for _, v := range []int{7, 14, 15, 20, 30, 21, 7} { - 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 := "" + var l []int m := make(map[int]int) - for i := 0; len(m) < 10; i++ { - v := randomdata.Number(0, 10000) + for i := 0; len(l) < CompartorSize; i++ { + v := randomdata.Number(0, NumberMax) 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) + l = append(l, v) } } - t.Error(godsavl.String()) + + var result bytes.Buffer + encoder := gob.NewEncoder(&result) + encoder.Encode(l) + lbytes := result.Bytes() + f.Write(lbytes) + +} + +func loadTestData() []int { + data, err := ioutil.ReadFile("../l.log") + if err != nil { + log.Println(err) + } + var l []int + decoder := gob.NewDecoder(bytes.NewReader(data)) + decoder.Decode(&l) + return l +} + +func TestDupKey(t *testing.T) { + tree1 := New(utils.IntComparator) + tree2 := avltree.NewWithIntComparator() + + for i := 0; i < CompartorSize/1000; i++ { + v := randomdata.Number(0, NumberMax) + tree1.Put(v) + tree2.Put(v, v) + } + + tree1.Put(500) + tree2.Put(500, 500) + + tree1.Put(500) + tree2.Put(500, 500) + + if tree1.Size() == tree2.Size() { + t.Error("tree size is equal") + } + + if tree1.String() == tree2.String() { + t.Error(tree1.String()) + } +} + +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) + + } + // ` AVLTree + // │ ┌── 30 + // │ │ └── 21 + // │ ┌── 20 + // │ │ └── 15 + // └── 14 + // │ ┌── 7 + // │ ┌── 7 + // │ │ └── 6 + // └── 5 + // │ ┌── 4 + // │ │ └── 3 + // └── 2 + // └── 1` + + iter := avl.Iterator() // root start point + + l := []int{14, 15, 20, 21, 30} + + for i := 0; iter.Prev(); i++ { + if iter.Value().(int) != l[i] { + t.Error("iter prev error", iter.Value(), l[i]) + } + } + + iter.Prev() + if iter.Value().(int) != 30 { + t.Error("prev == false", iter.Value(), iter.Prev(), iter.Value()) + } + + l = []int{21, 20, 15, 14, 7, 7, 6, 5, 4, 3, 2, 1} + for i := 0; iter.Next(); i++ { // cur is 30 next is 21 + if iter.Value().(int) != l[i] { + t.Error(iter.Value()) + } + } + + if iter.Next() != false { + t.Error("Next is error, cur is tail, val = 1 Next return false") + } + if iter.Value().(int) != 1 { // cur is 1 + t.Error("next == false", iter.Value(), iter.Next(), iter.Value()) + } + + if iter.Prev() != true && iter.Value().(int) != 2 { + t.Error("next to prev is error") + } +} + +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} { + avl.Put(v) + } + + if spew.Sprint(avl.GetAround(30)) != "[40 30 21]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(30))) + } + + if spew.Sprint(avl.GetAround(40)) != "[40 40 30]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(50))) + } + + if spew.Sprint(avl.GetAround(50)) != "[ 50 40]" { + t.Error("avl.GetAround(40)) is error", spew.Sprint(avl.GetAround(50))) + } +} + +// for test error case +func TestPutStable(t *testing.T) { + // avl := New(utils.IntComparator) + // gods := avltree.NewWithIntComparator() + // // 44908, 34985, 62991, 4201, 27210, 30707 + // for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + // t.Error(v) + // t.Error(avl.debugString()) + // avl.Put(v) + // gods.Put(v, v) + // t.Error(avl.debugString()) + // t.Error(gods.String()) + // } } func TestPutComparatorRandom(t *testing.T) { - for n := 0; n < 1000000; n++ { + for n := 0; n < 300000; n++ { avl := New(utils.IntComparator) godsavl := avltree.NewWithIntComparator() content := "" - for i := 0; avl.size < 10; i++ { + m := make(map[int]int) + for i := 0; len(m) < 10; i++ { v := randomdata.Number(0, 65535) - content += spew.Sprint(v) + " " - avl.Put(v) - godsavl.Put(v, v) - + 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(content) + t.Error(godsavl.String()) + t.Error(avl.debugString()) + 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)) + for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + avl.Put(v) } - t.Error(avl.String()) - t.Error(avl.Get(500)) + + result := ` +│ ┌── 57092 +│ ┌── 39016 +│ │ └── 36513 +│ ┌── 27897 +│ │ │ ┌── 23202 +│ │ └── 22574 +└── 7666 + │ ┌── 3055 + └── 2383 + └── 1562 +` + + s1 := avl.String() + s2 := "AVLTree" + result + if s1 != s2 { + t.Error(s1, s2) + } + + for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} { + v, ok := avl.Get(v) + if !ok { + t.Error("the val not found ", v) + } + } + + if v, ok := avl.Get(10000); ok { + t.Error("the val(1000) is not in tree, but is found", v) + } + } 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) - +ALL: + for c := 0; c < 5000; c++ { avl := New(utils.IntComparator) + gods := avltree.NewWithIntComparator() var l []int - for i := 0; i < 100; i++ { + m := make(map[int]int) + + for i := 0; len(l) < 100; i++ { v := randomdata.Number(0, 100000) - l = append(l, v) - avl.Put(v) + if _, ok := m[v]; !ok { + m[v] = v + l = append(l, v) + avl.Put(v) + gods.Put(v, 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]) + gods.Remove(l[i]) + s1 := spew.Sprint(avl.TraversalDepth(-1)) + s2 := spew.Sprint(gods.Values()) + if s1 != s2 { + t.Error("avl remove error", "avlsize = ", avl.Size()) + t.Error(s1) + t.Error(s2) + break ALL + } } } } 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; avl.size < 10; i++ { + for i := 0; len(l) < 10; i++ { v := randomdata.Number(0, 100) - - l = append(l, v) - avl.Put(v) - gods.Put(v, v) - + if _, ok := m[v]; !ok { + l = append(l, v) + m[v] = v + avl.Put(v) + gods.Put(v, v) + } } src1 := avl.String() @@ -186,124 +310,187 @@ ALL: // t.Error(avl.TraversalDepth(-1)) // t.Error(gods.Values()) break ALL - } } } } -const PutCompartorSize = 300000 -const NumberMax = 60000000 +func BenchmarkIterator(b *testing.B) { + tree := New(utils.IntComparator) + + l := loadTestData() + b.N = len(l) + + for _, v := range l { + tree.Put(v) + } + + b.ResetTimer() + b.StartTimer() + iter := tree.Iterator() + for iter.Next() { + } + for iter.Prev() { + } + for iter.Next() { + } + +} + +func BenchmarkGodsIterator(b *testing.B) { + tree := avltree.NewWithIntComparator() + + l := loadTestData() + b.N = len(l) + + for _, v := range l { + tree.Put(v, v) + } + + b.ResetTimer() + b.StartTimer() + iter := tree.Iterator() + for iter.Next() { + } + for iter.Prev() { + } + for iter.Next() { + } +} func BenchmarkRemove(b *testing.B) { + tree := New(utils.IntComparator) - avl := New(utils.IntComparator) - b.N = PutCompartorSize + l := loadTestData() - var l []int - for i := 0; i < b.N; i++ { - v := randomdata.Number(0, NumberMax) - l = append(l, v) - avl.Put(v) + b.N = len(l) + for _, v := range l { + tree.Put(v) } b.ResetTimer() b.StartTimer() - for i := 0; i < b.N; i++ { - avl.Remove(l[i]) + for i := 0; i < len(l); i++ { + tree.Remove(l[i]) } } func BenchmarkGodsRemove(b *testing.B) { - avl := avltree.NewWithIntComparator() - b.N = PutCompartorSize + tree := avltree.NewWithIntComparator() - var l []int - for i := 0; i < b.N; i++ { - v := randomdata.Number(0, NumberMax) - l = append(l, v) - avl.Put(v, v) + l := loadTestData() + + b.N = len(l) + for _, v := range l { + tree.Put(v, v) } b.ResetTimer() b.StartTimer() - for i := 0; i < b.N; i++ { - avl.Remove(l[i]) + 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) { + avl := New(utils.IntComparator) - b.N = PutCompartorSize - for i := 0; i < b.N/2; i++ { - avl.Put(randomdata.Number(0, NumberMax)) - } + l := loadTestData() + b.N = len(l) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { - avl.Get(randomdata.Number(0, NumberMax)) + avl.Get(l[i]) } } func BenchmarkGodsRBGet(b *testing.B) { - rb := redblacktree.NewWithIntComparator() + tree := redblacktree.NewWithIntComparator() - b.N = PutCompartorSize - for i := 0; i < b.N/2; i++ { - rb.Put(randomdata.Number(0, NumberMax), i) - } + l := loadTestData() + b.N = len(l) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { - rb.Get(randomdata.Number(0, NumberMax)) + tree.Get(l[i]) } } func BenchmarkGodsAvlGet(b *testing.B) { - rb := avltree.NewWithIntComparator() + tree := avltree.NewWithIntComparator() - b.N = PutCompartorSize - for i := 0; i < b.N/2; i++ { - rb.Put(randomdata.Number(0, NumberMax), i) - } + l := loadTestData() + b.N = len(l) b.ResetTimer() b.StartTimer() for i := 0; i < b.N; i++ { - rb.Get(randomdata.Number(0, NumberMax)) + tree.Get(l[i]) } } func BenchmarkPut(b *testing.B) { avl := New(utils.IntComparator) - b.N = PutCompartorSize - for i := 0; i < b.N; i++ { - avl.Put(randomdata.Number(0, NumberMax)) + l := loadTestData() + + b.ResetTimer() + b.StartTimer() + + b.N = len(l) + for _, v := range l { + avl.Put(v) } } func BenchmarkGodsRBPut(b *testing.B) { - rb := redblacktree.NewWithIntComparator() + tree := redblacktree.NewWithIntComparator() - b.N = PutCompartorSize - for i := 0; i < b.N; i++ { - rb.Put(randomdata.Number(0, NumberMax), i) + l := loadTestData() + + b.ResetTimer() + b.StartTimer() + + b.N = len(l) + for _, v := range l { + tree.Put(v, v) } - } func BenchmarkGodsPut(b *testing.B) { - avl := avltree.NewWithIntComparator() + tree := avltree.NewWithIntComparator() - b.N = PutCompartorSize - for i := 0; i < b.N; i++ { - avl.Put(randomdata.Number(0, NumberMax), i) + l := loadTestData() + + b.ResetTimer() + b.StartTimer() + + b.N = len(l) + for _, v := range l { + tree.Put(v, v) } } diff --git a/avldup/iterator.go b/avldup/iterator.go index 9a09c27..3d9c9ca 100644 --- a/avldup/iterator.go +++ b/avldup/iterator.go @@ -5,7 +5,7 @@ import ( ) type Iterator struct { - op *AVLDup + op *Tree dir int up *Node @@ -14,7 +14,7 @@ type Iterator struct { // curnext *Node } -func initIterator(avltree *AVLDup) *Iterator { +func initIterator(avltree *Tree) *Iterator { iter := &Iterator{op: avltree, tstack: lastack.New()} iter.up = avltree.root return iter @@ -100,9 +100,16 @@ func (iter *Iterator) Next() (result bool) { return false } +func getRelationship(cur *Node) int { + if cur.parent.children[1] == cur { + return 1 + } + return 0 +} + func (iter *Iterator) getNextUp(cur *Node) *Node { - for cur != nil { - if cur.child == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序 + for cur.parent != nil { + if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序 return cur.parent } cur = cur.parent @@ -123,8 +130,8 @@ func (iter *Iterator) curPushNextStack(cur *Node) { } func (iter *Iterator) getPrevUp(cur *Node) *Node { - for cur != nil { - if cur.child == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序 + for cur.parent != nil { + if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序 return cur.parent } cur = cur.parent diff --git a/avlkey/avlkey.go b/avlkey/avlkey.go index 7911dc0..c70f838 100644 --- a/avlkey/avlkey.go +++ b/avlkey/avlkey.go @@ -1,4 +1,4 @@ -package avl +package avlkey import ( "github.com/davecgh/go-spew/spew" diff --git a/avlkey/avlkey_test.go b/avlkey/avlkey_test.go index ed2c930..041c576 100644 --- a/avlkey/avlkey_test.go +++ b/avlkey/avlkey_test.go @@ -1,4 +1,4 @@ -package avl +package avlkey import ( "bytes" diff --git a/avlkey/iterator.go b/avlkey/iterator.go index 3ca4567..3067284 100644 --- a/avlkey/iterator.go +++ b/avlkey/iterator.go @@ -1,4 +1,4 @@ -package avl +package avlkey import ( "474420502.top/eson/structure/lastack" diff --git a/avlkeydup/avlkeydup.go b/avlkeydup/avlkeydup.go index 1f43ff9..fe4677a 100644 --- a/avlkeydup/avlkeydup.go +++ b/avlkeydup/avlkeydup.go @@ -1,4 +1,4 @@ -package avl +package avlkeydup import ( "github.com/davecgh/go-spew/spew" diff --git a/avlkeydup/avlkeydup_test.go b/avlkeydup/avlkeydup_test.go index 22c940a..c418fa4 100644 --- a/avlkeydup/avlkeydup_test.go +++ b/avlkeydup/avlkeydup_test.go @@ -1,4 +1,4 @@ -package avl +package avlkeydup import ( "bytes" diff --git a/avlkeydup/iterator.go b/avlkeydup/iterator.go index 3ca4567..c8e325b 100644 --- a/avlkeydup/iterator.go +++ b/avlkeydup/iterator.go @@ -1,4 +1,4 @@ -package avl +package avlkeydup import ( "474420502.top/eson/structure/lastack"