TODO: avlkey

This commit is contained in:
huangsimin
2019-03-13 19:09:24 +08:00
parent 226627f03e
commit b7e6045064
9 changed files with 1675 additions and 93 deletions

View File

@@ -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 {

View File

@@ -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()

145
avldup/iterator.go Normal file
View File

@@ -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)
}
}
}