完善平衡因子

This commit is contained in:
eson 2019-03-21 04:39:25 +08:00
parent 7dcde4cb97
commit a326f49962
2 changed files with 176 additions and 4 deletions

View File

@ -333,14 +333,15 @@ func (avl *Tree) Put(value interface{}) {
fsize := getSize(fixed) fsize := getSize(fixed)
if fsize == 3 { if fsize == 3 {
lefts, rigths := getChildrenSize(fixed) lefts, rigths := getChildrenSize(fixed)
avl.fixPutHeight(fixed, lefts, rigths) avl.fix3PutHeight(fixed, lefts, rigths)
} }
return return
} }
if cur.size > 9 { if cur.size > 9 {
ls, rs := cur.children[0].size, cur.children[1].size ls, rs := cur.children[0].size, cur.children[1].size
if rs >= ls*2 || ls >= rs*2 { factor := cur.size / 10 // or factor = 1
if rs >= ls*2+factor || ls >= rs*2+factor {
avl.fixPutHeight(cur, ls, rs) avl.fixPutHeight(cur, ls, rs)
} }
} }
@ -499,6 +500,29 @@ func (avl *Tree) Traversal(every func(v interface{}) bool, traversalMethod ...in
} }
} }
func (avl *Tree) lrrotate3(cur *Node) {
const l = 1
const r = 0
movparent := cur.children[l]
mov := movparent.children[r]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
cur.children[r] = mov
mov.parent = cur
cur.children[l] = movparent
movparent.children[r] = nil
cur.children[r] = mov
mov.parent = cur
// cur.size = 3
// cur.children[r].size = 1
cur.children[l].size = 1
}
func (avl *Tree) lrrotate(cur *Node) { func (avl *Tree) lrrotate(cur *Node) {
const l = 1 const l = 1
@ -547,6 +571,29 @@ func (avl *Tree) lrrotate(cur *Node) {
// cur.height = getMaxChildrenHeight(cur) + 1 // cur.height = getMaxChildrenHeight(cur) + 1
} }
func (avl *Tree) rlrotate3(cur *Node) {
const l = 0
const r = 1
movparent := cur.children[l]
mov := movparent.children[r]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
cur.children[r] = mov
mov.parent = cur
cur.children[l] = movparent
movparent.children[r] = nil
cur.children[r] = mov
mov.parent = cur
// cur.size = 3
// cur.children[r].size = 1
cur.children[l].size = 1
}
func (avl *Tree) rlrotate(cur *Node) { func (avl *Tree) rlrotate(cur *Node) {
const l = 0 const l = 0
@ -585,6 +632,25 @@ func (avl *Tree) rlrotate(cur *Node) {
cur.size = getChildrenSumSize(cur) + 1 cur.size = getChildrenSumSize(cur) + 1
} }
func (avl *Tree) rrotate3(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
cur.children[r] = mov
mov.size = 1
cur.children[l] = mov.children[l]
cur.children[l].parent = cur
mov.children[l] = nil
mov.size = 1
}
func (avl *Tree) rrotate(cur *Node) { func (avl *Tree) rrotate(cur *Node) {
const l = 0 const l = 0
@ -628,6 +694,25 @@ func (avl *Tree) rrotate(cur *Node) {
// cur.height = getMaxChildrenHeight(cur) + 1 // cur.height = getMaxChildrenHeight(cur) + 1
} }
func (avl *Tree) lrotate3(cur *Node) {
const l = 1
const r = 0
// 1 right 0 left
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
cur.children[r] = mov
mov.size = 1
cur.children[l] = mov.children[l]
cur.children[l].parent = cur
mov.children[l] = nil
mov.size = 1
}
func (avl *Tree) lrotate(cur *Node) { func (avl *Tree) lrotate(cur *Node) {
const l = 1 const l = 1
@ -698,6 +783,26 @@ func (avl *Tree) fixRemoveHeight(cur *Node) {
} }
} }
func (avl *Tree) fix3PutHeight(cur *Node, lefts, rigths int) {
if lefts > rigths {
l := cur.children[0]
llsize, lrsize := getChildrenSize(l)
if lrsize > llsize {
avl.rlrotate3(cur)
} else {
avl.rrotate3(cur)
}
} else {
r := cur.children[1]
rlsize, rrsize := getChildrenSize(r)
if rlsize > rrsize {
avl.lrrotate3(cur)
} else {
avl.lrotate3(cur)
}
}
}
func (avl *Tree) fixPutHeight(cur *Node, lefts, rigths int) { func (avl *Tree) fixPutHeight(cur *Node, lefts, rigths int) {
if lefts > rigths { if lefts > rigths {
l := cur.children[0] l := cur.children[0]

View File

@ -8,6 +8,8 @@ import (
"os" "os"
"testing" "testing"
"github.com/huandu/skiplist"
"github.com/Pallinder/go-randomdata" "github.com/Pallinder/go-randomdata"
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/avltree" "github.com/emirpasic/gods/trees/avltree"
@ -15,7 +17,7 @@ import (
"github.com/emirpasic/gods/utils" "github.com/emirpasic/gods/utils"
) )
const CompartorSize = 100000 const CompartorSize = 1000000
const NumberMax = 50000000 const NumberMax = 50000000
func TestSave(t *testing.T) { func TestSave(t *testing.T) {
@ -69,6 +71,7 @@ func TestIterator(t *testing.T) {
// } // }
// t.Error(avl.Values()) // t.Error(avl.Values())
// t.Error(avl.debugString()) // t.Error(avl.debugString())
} }
func TestGetRange(t *testing.T) { func TestGetRange(t *testing.T) {
@ -305,6 +308,70 @@ ALL:
} }
} }
func BenchmarkSkipListGet(b *testing.B) {
sl := skiplist.New(skiplist.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
sl.Set(v, v)
}
b.ResetTimer()
b.StartTimer()
execCount := 5
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
e := sl.Get(v)
var result [50]interface{}
for i := 0; i < 50 && e != nil; i++ {
result[i] = e.Value
e = e.Next()
}
}
}
}
func BenchmarkGetRange(b *testing.B) {
tree := New(utils.IntComparator)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v)
}
b.ResetTimer()
b.StartTimer()
execCount := 5
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for range l {
tree.GetRange(i, i+49)
}
}
}
func BenchmarkSkipListSet(b *testing.B) {
sl := skiplist.New(skiplist.Int)
l := loadTestData()
execCount := 50
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
sl.Set(v, v)
}
}
}
func BenchmarkIterator(b *testing.B) { func BenchmarkIterator(b *testing.B) {
tree := New(utils.IntComparator) tree := New(utils.IntComparator)
@ -458,7 +525,7 @@ func BenchmarkPut(b *testing.B) {
b.ResetTimer() b.ResetTimer()
b.StartTimer() b.StartTimer()
execCount := 500 execCount := 50
b.N = len(l) * execCount b.N = len(l) * execCount
for i := 0; i < execCount; i++ { for i := 0; i < execCount; i++ {
avl := New(utils.IntComparator) avl := New(utils.IntComparator)