TODO: avlkey
This commit is contained in:
139
avldup/avldup.go
139
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 {
|
||||
|
||||
|
||||
@@ -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
145
avldup/iterator.go
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user