getAround 完美完成

This commit is contained in:
huangsimin
2019-03-21 15:27:08 +08:00
parent a326f49962
commit c6b06a9c3b
6 changed files with 2058 additions and 76 deletions

View File

@@ -186,7 +186,7 @@ func (avl *Tree) Values() []interface{} {
return result
}
func (avl *Tree) GetRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1
func (avl *Tree) IndexRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1
if idx1^idx2 < 0 {
if idx1 < 0 {
@@ -244,16 +244,20 @@ func (avl *Tree) GetRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0
return nil, false
}
func (avl *Tree) Get(key interface{}) (interface{}, bool) {
n, ok := avl.GetNode(key)
// func (avl *Tree) GetRange(v1, v2 interface{}) {
// avl.getArountNode(v1)
// }
func (avl *Tree) Get(value interface{}) (interface{}, bool) {
n, ok := avl.GetNode(value)
if ok {
return n.value, true
}
return n, false
}
func (avl *Tree) GetAround(key interface{}) (result [3]interface{}) {
an := avl.GetAroundNode(key)
func (avl *Tree) GetAround(value interface{}) (result [3]interface{}) {
an := avl.getArountNode(value)
for i, n := range an {
if n != nil {
result[i] = n.value
@@ -262,38 +266,174 @@ func (avl *Tree) GetAround(key interface{}) (result [3]interface{}) {
return
}
func (avl *Tree) GetAroundNode(value interface{}) (result [3]*Node) {
func (avl *Tree) getArountNode(value interface{}) (result [3]*Node) {
var last *Node
var lastc int
if cur, ok := avl.GetNode(value); ok {
var iter *Iterator
iter = NewIterator(cur)
iter.curPushPrevStack(iter.up)
iter.up = iter.getPrevUp(iter.up)
if v, ok := iter.tstack.Pop(); ok {
result[0] = v.(*Node)
// iter.curPushPrevStack(iter.cur)
} else {
result[0] = iter.up
for n := avl.root; n != nil; {
last = n
c := avl.comparator(value, n.value)
switch c {
case -1:
n = n.children[0]
lastc = c
case 1:
n = n.children[1]
lastc = c
case 0:
result[1] = n
n = nil
default:
panic("Get comparator only is allowed in -1, 0, 1")
}
iter = NewIterator(cur)
iter.curPushNextStack(iter.up)
iter.up = iter.getNextUp(iter.up)
if v, ok := iter.tstack.Pop(); ok {
result[2] = v.(*Node)
// iter.curPushNextStack(iter.cur)
} else {
result[2] = iter.up
}
result[1] = cur
}
switch lastc {
case 1:
const il = 0
const ir = 1
if result[1] == nil {
result[0] = last
} else {
l := result[1].children[il]
r := result[1].children[ir]
if l == nil {
result[0] = result[1].parent
} else {
for l.children[ir] != nil {
l = l.children[ir]
}
result[0] = l
}
if r == nil {
parent := result[1].parent
for ; parent != nil && parent.parent != nil; parent = parent.parent {
child := getRelationship(parent)
if child == (-lastc+2)/2 { // child 与 comparator 后左右的关系
result[2] = parent.parent
break
}
}
} else {
for r.children[il] != nil {
r = r.children[il]
}
result[2] = r
}
}
case -1:
const il = 1
const ir = 0
if result[1] == nil {
result[2] = last
} else {
l := result[1].children[il]
r := result[1].children[ir]
if l == nil {
result[2] = result[1].parent
} else {
for l.children[ir] != nil {
l = l.children[ir]
}
result[2] = l
}
if r == nil {
parent := result[1].parent
for ; parent != nil && parent.parent != nil; parent = parent.parent {
child := getRelationship(parent)
if child == (-lastc+2)/2 { // child 与 comparator 后左右的关系
result[0] = parent.parent
break
}
}
} else {
for r.children[il] != nil {
r = r.children[il]
}
result[0] = r
}
}
case 0:
const il = 0
const ir = 1
if result[1] == nil {
return
}
l := result[1].children[il]
r := result[1].children[ir]
if l == nil {
result[0] = nil
} else {
for l.children[ir] != nil {
l = l.children[ir]
}
result[0] = l
}
if r == nil {
result[2] = nil
} else {
for r.children[il] != nil {
r = r.children[il]
}
result[2] = r
}
}
return
}
// func (avl *Tree) GetAroundNode(value interface{}) (result [3]*Node) {
// if cur, ok := avl.GetNode(value); ok {
// var iter *Iterator
// iter = NewIterator(cur)
// iter.curPushPrevStack(iter.up)
// iter.up = iter.getPrevUp(iter.up)
// if v, ok := iter.tstack.Pop(); ok {
// result[2] = v.(*Node)
// // iter.curPushPrevStack(iter.cur)
// } else {
// result[2] = iter.up
// }
// iter = NewIterator(cur)
// iter.curPushNextStack(iter.up)
// iter.up = iter.getNextUp(iter.up)
// if v, ok := iter.tstack.Pop(); ok {
// result[0] = v.(*Node)
// // iter.curPushNextStack(iter.cur)
// } else {
// result[0] = iter.up
// }
// result[1] = cur
// }
// return
// }
func (avl *Tree) GetNode(value interface{}) (*Node, bool) {
for n := avl.root; n != nil; {
@@ -338,7 +478,7 @@ func (avl *Tree) Put(value interface{}) {
return
}
if cur.size > 9 {
if cur.size > 8 {
ls, rs := cur.children[0].size, cur.children[1].size
factor := cur.size / 10 // or factor = 1
if rs >= ls*2+factor || ls >= rs*2+factor {
@@ -773,9 +913,10 @@ func getSize(cur *Node) int {
func (avl *Tree) fixRemoveHeight(cur *Node) {
for cur != nil {
cur.size--
if cur.size > 9 {
if cur.size > 8 {
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)
}
}

View File

@@ -74,7 +74,7 @@ func TestIterator(t *testing.T) {
}
func TestGetRange(t *testing.T) {
func TestIndexRange(t *testing.T) {
tree := New(utils.IntComparator)
l := []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15}
for _, v := range l {
@@ -84,79 +84,121 @@ func TestGetRange(t *testing.T) {
// t.Error(tree.Values(), tree.Size())
var result string
result = spew.Sprint(tree.GetRange(0, 5))
result = spew.Sprint(tree.IndexRange(0, 5))
if result != "[3 7 14 14 14 15] true" {
t.Error(result)
}
result = spew.Sprint(tree.GetRange(2, 5))
result = spew.Sprint(tree.IndexRange(2, 5))
if result != "[14 14 14 15] true" {
t.Error(result)
}
result = spew.Sprint(tree.GetRange(10, 100))
result = spew.Sprint(tree.IndexRange(10, 100))
if result != "[30 40 40 40 40 50] false" {
t.Error(result)
}
result = spew.Sprint(tree.GetRange(15, 0)) // size = 16, index max = 15
result = spew.Sprint(tree.IndexRange(15, 0)) // size = 16, index max = 15
if result != "[50 40 40 40 40 30 21 20 17 16 15 14 14 14 7 3] true" {
t.Error(result)
}
result = spew.Sprint(tree.GetRange(16, 0)) // size = 16, index max = 15
result = spew.Sprint(tree.IndexRange(16, 0)) // size = 16, index max = 15
if result != "[50 40 40 40 40 30 21 20 17 16 15 14 14 14 7 3] false" {
t.Error(result)
}
result = spew.Sprint(tree.GetRange(5, 1)) // size = 16, index max = 15
result = spew.Sprint(tree.IndexRange(5, 1)) // size = 16, index max = 15
if result != "[15 14 14 14 7] true" {
t.Error(result)
}
result = spew.Sprint(tree.GetRange(-1, -5)) // size = 16, index max = 15
result = spew.Sprint(tree.IndexRange(-1, -5)) // size = 16, index max = 15
if result != "[50 40 40 40 40] true" {
t.Error(result)
}
result = spew.Sprint(tree.GetRange(-1, -16)) // size = 16, index max = 0 - 15 (-1,-16)
result = spew.Sprint(tree.IndexRange(-1, -16)) // size = 16, index max = 0 - 15 (-1,-16)
if result != "[50 40 40 40 40 30 21 20 17 16 15 14 14 14 7 3] true" {
t.Error(result)
}
result = spew.Sprint(tree.GetRange(-1, -17)) // size = 16, index max = 0 - 15 (-1,-16)
result = spew.Sprint(tree.IndexRange(-1, -17)) // size = 16, index max = 0 - 15 (-1,-16)
if result != "[50 40 40 40 40 30 21 20 17 16 15 14 14 14 7 3] false" {
t.Error(result)
}
result = spew.Sprint(tree.GetRange(-5, -1)) // size = 16, index max = 0 - 15 (-1,-16)
result = spew.Sprint(tree.IndexRange(-5, -1)) // size = 16, index max = 0 - 15 (-1,-16)
if result != "[40 40 40 40 50] true" {
t.Error(result)
}
}
func TestGetAround(t *testing.T) {
avl := New(utils.IntComparator)
tree := New(utils.IntComparator)
for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
avl.Put(v)
tree.Put(v)
}
var Result string
Result = spew.Sprint(avl.GetAround(3))
if Result != "[7 3 <nil>]" {
t.Error("avl.GetAround(3)) is error", Result)
Result = spew.Sprint(tree.GetAround(17))
if Result != "[16 17 20]" {
t.Error(tree.Values())
t.Error("17 is root, tree.GetAround(17)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(avl.GetAround(40))
if Result != "[40 40 30]" {
t.Error("avl.GetAround(40)) is error", Result)
Result = spew.Sprint(tree.GetAround(3))
if Result != "[<nil> 3 7]" {
t.Error(tree.Values())
t.Error("tree.GetAround(3)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(avl.GetAround(50))
if Result != "[<nil> 50 40]" {
t.Error("avl.GetAround(50)) is error", Result)
Result = spew.Sprint(tree.GetAround(40))
if Result != "[30 40 40]" {
t.Error(tree.Values())
t.Error("tree.GetAround(40)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(tree.GetAround(50))
if Result != "[40 50 <nil>]" {
t.Error(tree.Values())
t.Error("tree.GetAround(50)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(tree.GetAround(18))
if Result != "[<nil> <nil> 20]" {
t.Error(tree.Values())
t.Error("18 is not in list, tree.GetAround(18)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(tree.GetAround(5))
if Result != "[3 <nil> <nil>]" {
t.Error(tree.Values())
t.Error("5 is not in list, tree.GetAround(5)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(tree.GetAround(2))
if Result != "[<nil> <nil> 3]" {
t.Error(tree.Values())
t.Error("2 is not in list, tree.GetAround(2)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(tree.GetAround(100))
if Result != "[50 <nil> <nil>]" {
t.Error(tree.Values())
t.Error("50 is not in list, tree.GetAround(50)) is error", Result)
t.Error(tree.debugString())
}
}
// // for test error case
@@ -352,7 +394,7 @@ func BenchmarkGetRange(b *testing.B) {
for i := 0; i < execCount; i++ {
for range l {
tree.GetRange(i, i+49)
tree.IndexRange(i, i+49)
}
}
}
@@ -538,25 +580,56 @@ func BenchmarkPut(b *testing.B) {
func TestPutStable(t *testing.T) {
// l := []int{14, 18, 20, 21, 22, 23, 19}
var l []int
for i := 0; len(l) < 10; i++ {
l = append(l, randomdata.Number(0, 65))
}
for n := 0; n < 1000000; n++ {
var l []int
l = append(l, 60, 5, 15)
for i := 0; len(l) < 11; i++ {
l = append(l, randomdata.Number(3, 69))
}
avl := New(utils.IntComparator)
for _, v := range l {
avl.Put(v)
t.Error(avl.debugString(), v)
}
t.Error(avl.Values())
for _, v := range []int{10, 0, 9, 5, -11, -10, -1, -5} {
t.Error(avl.Index(v))
}
avl := New(utils.IntComparator)
for _, v := range l {
avl.Put(v)
}
result := avl.getArountNode(60)
avl.RemoveIndex(4)
t.Error(avl.Index(4))
t.Error(avl.Values())
t.Error(avl.debugString())
if result[2] == nil && avl.indexNode(-1) != result[1] {
t.Error(avl.debugString())
t.Error(avl.Values())
t.Error(result)
}
result = avl.getArountNode(5)
if result[0] == nil && avl.indexNode(0) != result[1] {
t.Error(avl.debugString())
t.Error(avl.Values())
t.Error(result)
}
result = avl.getArountNode(2)
if result[2] == nil && avl.indexNode(0) != result[2] {
t.Error(avl.debugString())
t.Error(avl.Values())
t.Error(result)
}
result = avl.getArountNode(70)
if result[0] == nil && avl.indexNode(-1) != result[0] {
t.Error(avl.debugString())
t.Error(avl.Values())
t.Error(result)
}
}
// for _, v := range []int{10, 0, 9, 5, -11, -10, -1, -5} {
// t.Error(avl.Index(v))
// // t.Error(avl.debugString())
// }
// avl.RemoveIndex(4)
// t.Error(avl.Index(4))
// t.Error(avl.Values())
// t.Error(avl.debugString())
// t.Error(len(l), avl.debugString(), "\n", "-----------") // 3 6(4)
}