new file: .gitignore

new file:   LICENSE
new file:   README.md
new file:   compare/compare.go
new file:   for_test.go
new file:   heap/heap.go
new file:   heap/heap_test.go
new file:   interface.go
new file:   lastack/lastack.go
new file:   lastack/lastack_test.go
new file:   list/list.go
new file:   list/list_test.go
new file:   map/hashmap/hashmap.go
new file:   map/hashmap/hashmap_test.go
new file:   priority_list/iterator.go
new file:   priority_list/priority_list.go
new file:   priority_list/priority_list_test.go
new file:   priority_queue/iterator.go
new file:   priority_queue/priority_queue.go
new file:   priority_queue/priority_queue_test.go
new file:   priority_queue/vbt.go
new file:   priority_queue/vbt_test.go
new file:   priority_queuekey/iterator.go
new file:   priority_queuekey/priority_queuekey.go
new file:   priority_queuekey/priority_queuekey_test.go
new file:   priority_queuekey/vbt.go
new file:   priority_queuekey/vbt_test.go
new file:   set/hashset/hashset.go
new file:   set/hashset/hashset_test.go
new file:   set/treeset/treeset.go
new file:   set/treeset/treeset_test.go
new file:   sparse_array/array2/array2.go
new file:   sparse_array/array2/array2_test.go
new file:   sparse_array/array3/array3.go
new file:   sparse_array/array3/array3_test.go
new file:   sparse_array/arrayn/arrayn.go
new file:   sparse_array/arrayn/arrayn_test.go
new file:   stack/stack.go
new file:   stack/stack_test.go
new file:   tree/avl/avl.go
new file:   tree/avl/avl_test.go
new file:   tree/avl/iterator.go
new file:   tree/avldup/avldup.go
new file:   tree/avldup/avldup_test.go
new file:   tree/avldup/iterator.go
new file:   tree/avlkey/avlkey.go
new file:   tree/avlkey/avlkey_test.go
new file:   tree/avlkey/iterator.go
new file:   tree/avlkeydup/avlkeydup.go
new file:   tree/avlkeydup/avlkeydup_test.go
new file:   tree/avlkeydup/iterator.go
new file:   tree/vbt/iterator.go
new file:   tree/vbt/vbt.go
new file:   tree/vbt/vbt_test.go
new file:   tree/vbtkey/iterator.go
new file:   tree/vbtkey/vbtkey.go
new file:   tree/vbtkey/vbtkey_test.go
This commit is contained in:
2019-05-08 10:42:51 +08:00
commit 368447c31d
57 changed files with 18364 additions and 0 deletions

14
.gitignore vendored Normal file
View File

@@ -0,0 +1,14 @@
# ---> Go
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
*.log
.vscode

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2
README.md Normal file
View File

@@ -0,0 +1,2 @@
# structure

245
compare/compare.go Normal file
View File

@@ -0,0 +1,245 @@
package compare
import "time"
// Compare 如下
// k1 > k2 --> 1
// k1 == k2 --> 0
// k1 < k2 --> -1
type Compare func(k1, k2 interface{}) int
// String comp
func String(k1, k2 interface{}) int {
s1 := k1.(string)
s2 := k2.(string)
switch {
case len(s1) > len(s2):
for i := 0; i < len(s2); i++ {
if s1[i] != s2[i] {
if s1[i] > s2[i] {
return 1
}
return -1
}
}
return 1
case len(s1) < len(s2):
for i := 0; i < len(s1); i++ {
if s1[i] != s2[i] {
if s1[i] > s2[i] {
return 1
}
return -1
}
}
return -1
default:
for i := 0; i < len(s1); i++ {
if s1[i] != s2[i] {
if s1[i] > s2[i] {
return 1
}
return -1
}
}
return 0
}
}
func Int(k1, k2 interface{}) int {
c1 := k1.(int)
c2 := k2.(int)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func Int8(k1, k2 interface{}) int {
c1 := k1.(int8)
c2 := k2.(int8)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func Int16(k1, k2 interface{}) int {
c1 := k1.(int16)
c2 := k2.(int16)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func Int32(k1, k2 interface{}) int {
c1 := k1.(int32)
c2 := k2.(int32)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func Int64(k1, k2 interface{}) int {
c1 := k1.(int64)
c2 := k2.(int64)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func UInt(k1, k2 interface{}) int {
c1 := k1.(uint)
c2 := k2.(uint)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func UInt8(k1, k2 interface{}) int {
c1 := k1.(uint8)
c2 := k2.(uint8)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func UInt16(k1, k2 interface{}) int {
c1 := k1.(uint16)
c2 := k2.(uint16)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func UInt32(k1, k2 interface{}) int {
c1 := k1.(uint32)
c2 := k2.(uint32)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func UInt64(k1, k2 interface{}) int {
c1 := k1.(uint64)
c2 := k2.(uint64)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func Float32(k1, k2 interface{}) int {
c1 := k1.(float32)
c2 := k2.(float32)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func Float64(k1, k2 interface{}) int {
c1 := k1.(float64)
c2 := k2.(float64)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func Byte(k1, k2 interface{}) int {
c1 := k1.(byte)
c2 := k2.(byte)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func Rune(k1, k2 interface{}) int {
c1 := k1.(rune)
c2 := k2.(rune)
switch {
case c1 > c2:
return 1
case c1 < c2:
return -1
default:
return 0
}
}
func Time(k1, k2 interface{}) int {
c1 := k1.(time.Time)
c2 := k2.(time.Time)
switch {
case c1.After(c2):
return 1
case c1.Before(c2):
return -1
default:
return 0
}
}

59
for_test.go Normal file
View File

@@ -0,0 +1,59 @@
package structure
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"os"
"testing"
randomdata "github.com/Pallinder/go-randomdata"
)
const CompartorSize = 1000000
const NumberMax = 50000000
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)
}
//fmt.Println(userBytes)
var l []int
// for i := 0; len(l) < 1000; i++ {
// v := randomdata.Number(0, 65535)
// l = append(l, v)
// }
//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
}

154
heap/heap.go Normal file
View File

@@ -0,0 +1,154 @@
package heap
import (
"474420502.top/eson/structure/compare"
)
type Heap struct {
size int
elements []interface{}
Compare compare.Compare
}
func New(Compare compare.Compare) *Heap {
h := &Heap{Compare: Compare}
h.elements = make([]interface{}, 16, 16)
return h
}
func (h *Heap) Size() int {
return h.size
}
func (h *Heap) Values() []interface{} {
return h.elements[0:h.size]
}
func (h *Heap) grow() {
ecap := len(h.elements)
if h.size >= ecap {
ecap = ecap << 1
grow := make([]interface{}, ecap, ecap)
copy(grow, h.elements)
h.elements = grow
}
}
func (h *Heap) Empty() bool {
return h.size < 1
}
func (h *Heap) Clear() {
h.size = 0
}
func (h *Heap) Reborn() {
h.size = 0
h.elements = make([]interface{}, 16, 16)
}
func (h *Heap) Top() (interface{}, bool) {
if h.size != 0 {
return h.elements[0], true
}
return nil, false
}
func (h *Heap) Push(v interface{}) {
if v == nil {
return
}
h.grow()
curidx := h.size
h.size++
// up
for curidx != 0 {
pidx := (curidx - 1) >> 1
pvalue := h.elements[pidx]
if h.Compare(v, pvalue) > 0 {
h.elements[curidx] = pvalue
curidx = pidx
} else {
break
}
}
h.elements[curidx] = v
}
func (h *Heap) slimming() {
elen := len(h.elements)
if elen >= 32 {
ecap := elen >> 1
if h.size <= ecap {
ecap = elen - (ecap >> 1)
slimming := make([]interface{}, ecap, ecap)
copy(slimming, h.elements)
h.elements = slimming
}
}
}
func (h *Heap) Pop() (interface{}, bool) {
if h.size == 0 {
return nil, false
}
curidx := 0
top := h.elements[curidx]
h.size--
h.slimming()
if h.size == 0 {
return top, true
}
downvalue := h.elements[h.size]
var cidx, c1, c2 int
var cvalue1, cvalue2, cvalue interface{}
// down
for {
cidx = curidx << 1
c2 = cidx + 2
if c2 < h.size {
cvalue2 = h.elements[c2]
c1 = cidx + 1
cvalue1 = h.elements[c1]
if h.Compare(cvalue1, cvalue2) >= 0 {
cidx = c1
cvalue = cvalue1
} else {
cidx = c2
cvalue = cvalue2
}
} else {
c1 = cidx + 1
if c1 < h.size {
cvalue1 = h.elements[c1]
cidx = c1
cvalue = cvalue1
} else {
break
}
}
if h.Compare(cvalue, downvalue) > 0 {
h.elements[curidx] = cvalue
curidx = cidx
} else {
break
}
}
h.elements[curidx] = downvalue
return top, true
}

182
heap/heap_test.go Normal file
View File

@@ -0,0 +1,182 @@
package heap
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"github.com/Pallinder/go-randomdata"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/binaryheap"
)
func Int(k1, k2 interface{}) int {
c1 := k1.(int)
c2 := k2.(int)
switch {
case c1 > c2:
return -1
case c1 < c2:
return 1
default:
return 0
}
}
func TestPush(t *testing.T) {
for i := 0; i < 1000000; i++ {
h := New(Int)
gods := binaryheap.NewWithIntComparator()
for c := 0; c < 20; c++ {
v := randomdata.Number(0, 100)
h.Push(v)
gods.Push(v)
}
r1 := spew.Sprint(h.Values())
r2 := spew.Sprint(gods.Values())
if r1 != r2 {
t.Error(r1)
t.Error(r2)
break
}
}
}
func TestPop(t *testing.T) {
for i := 0; i < 200000; i++ {
h := New(Int)
// m := make(map[int]int)
gods := binaryheap.NewWithIntComparator()
for c := 0; c < 40; c++ {
v := randomdata.Number(0, 100)
// if _, ok := m[v]; !ok {
h.Push(v)
gods.Push(v)
// m[v] = v
// }
}
// t.Error(h.Values())
// t.Error(gods.Values())
for c := 0; c < randomdata.Number(5, 10); c++ {
v1, _ := h.Pop()
v2, _ := gods.Pop()
if v1 != v2 {
t.Error(h.Values(), v1)
t.Error(gods.Values(), v2)
return
}
}
r1 := spew.Sprint(h.Values())
r2 := spew.Sprint(gods.Values())
if r1 != r2 {
t.Error(r1)
t.Error(r2)
break
}
}
}
func BenchmarkPush(b *testing.B) {
l := loadTestData()
b.ResetTimer()
execCount := 50
b.N = len(l) * execCount
for c := 0; c < execCount; c++ {
b.StopTimer()
h := New(Int)
b.StartTimer()
for _, v := range l {
h.Push(v)
}
}
}
func BenchmarkPop(b *testing.B) {
h := New(Int)
l := loadTestData()
b.ResetTimer()
execCount := 20
b.N = len(l) * execCount
for c := 0; c < execCount; c++ {
b.StopTimer()
for _, v := range l {
h.Push(v)
}
b.StartTimer()
for h.size != 0 {
h.Pop()
}
}
}
func BenchmarkGodsPop(b *testing.B) {
h := binaryheap.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
execCount := 20
b.N = len(l) * execCount
for c := 0; c < execCount; c++ {
b.StopTimer()
for _, v := range l {
h.Push(v)
}
b.StartTimer()
for h.Size() != 0 {
h.Pop()
}
}
}
func BenchmarkGodsPush(b *testing.B) {
l := loadTestData()
b.ResetTimer()
execCount := 50
b.N = len(l) * execCount
for c := 0; c < execCount; c++ {
b.StopTimer()
h := binaryheap.NewWith(Int)
b.StartTimer()
for _, v := range l {
h.Push(v)
}
}
}
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
}

1
interface.go Normal file
View File

@@ -0,0 +1 @@
package structure

167
lastack/lastack.go Normal file
View File

@@ -0,0 +1,167 @@
package lastack
import (
"github.com/davecgh/go-spew/spew"
)
type Node struct {
elements []interface{}
cur int
down *Node
}
type Stack struct {
top *Node
cache *Node
size int
}
func (as *Stack) grow() bool {
if as.top.cur+1 == cap(as.top.elements) {
var grownode *Node
if as.cache != nil {
grownode = as.cache
grownode.cur = -1
as.cache = nil
} else {
var growsize int
if as.size <= 256 {
growsize = as.size << 1
} else {
growsize = 256 + as.size>>2
}
grownode = &Node{elements: make([]interface{}, growsize, growsize), cur: -1}
}
grownode.down = as.top
as.top = grownode
return true
}
return false
}
func (as *Stack) cacheRemove() bool {
if as.top.cur == 0 && as.top.down != nil {
as.cache = as.top
as.top = as.top.down
as.cache.down = nil
return true
}
return false
}
func New() *Stack {
s := &Stack{}
s.size = 0
s.top = &Node{elements: make([]interface{}, 8, 8), cur: -1}
return s
}
func NewWithCap(cap int) *Stack {
s := &Stack{}
s.size = 0
s.top = &Node{elements: make([]interface{}, cap, cap), cur: -1}
return s
}
func (as *Stack) Clear() {
as.size = 0
as.top.down = nil
as.top.cur = -1
}
func (as *Stack) Empty() bool {
return as.size == 0
}
func (as *Stack) Size() int {
return as.size
}
func (as *Stack) String() string {
content := ""
cur := as.top
for ; cur != nil; cur = cur.down {
for i, _ := range cur.elements {
if cur.cur >= i {
content += spew.Sprint(cur.elements[cur.cur-i]) + " "
}
}
}
if len(content) > 0 {
content = content[0 : len(content)-1]
} else {
content = ""
}
return content
}
func (as *Stack) Values() []interface{} {
result := make([]interface{}, as.size, as.size)
cur := as.top
n := 0
for ; cur != nil; cur = cur.down {
for i, _ := range cur.elements {
if cur.cur >= i {
result[n] = cur.elements[cur.cur-i]
n++
}
}
}
return result
}
func (as *Stack) Get(idx int) (interface{}, bool) {
if idx < 0 {
return nil, false
}
cur := as.top
for cur != nil && idx-cur.cur > 0 {
idx = idx - cur.cur - 1
cur = cur.down
}
if cur == nil {
return nil, false
}
return cur.elements[cur.cur-idx], true
}
func (as *Stack) Push(v interface{}) {
as.grow()
as.top.cur++
as.top.elements[as.top.cur] = v
as.size++
}
func (as *Stack) Pop() (interface{}, bool) {
if as.size <= 0 {
return nil, false
}
as.size--
if as.cacheRemove() {
return as.cache.elements[as.cache.cur], true
}
epop := as.top.elements[as.top.cur]
as.top.cur--
return epop, true
}
func (as *Stack) Peek() (interface{}, bool) {
if as.size <= 0 {
return nil, false
}
return as.top.elements[as.top.cur], true
}

173
lastack/lastack_test.go Normal file
View File

@@ -0,0 +1,173 @@
package lastack
import (
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/stacks/arraystack"
"github.com/Pallinder/go-randomdata"
)
func TestPush(t *testing.T) {
var result string
s := New()
result = spew.Sprint(s.Values())
if result != "[]" {
t.Error(result)
}
l := []int{10, 7, 3, 4, 5, 15}
for _, v := range l {
s.Push(v)
}
result = spew.Sprint(s.Values())
if result != "[15 5 4 3 7 10]" {
t.Error(result)
}
if v, ok := s.Peek(); ok {
if v != 15 {
t.Error(v)
}
}
result = spew.Sprint(s.Values())
if result != "[15 5 4 3 7 10]" {
t.Error(result)
}
if v, ok := s.Pop(); ok {
if v != 15 {
t.Error(v)
}
}
result = spew.Sprint(s.Values())
if result != "[5 4 3 7 10]" {
t.Error(result)
}
for s.Size() != 1 {
s.Pop()
}
result = spew.Sprint(s.Values())
if result != "[10]" {
t.Error(result)
}
if v, ok := s.Pop(); ok {
if v != 10 {
t.Error(v)
}
}
result = spew.Sprint(s.Values())
if result != "[]" {
t.Error(result)
}
}
func BenchmarkGet(b *testing.B) {
s := New()
b.N = 20000000
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Get(i)
}
}
func BenchmarkPush(b *testing.B) {
s := New()
b.N = 20000000
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
}
func BenchmarkGodsPush(b *testing.B) {
s := arraystack.New()
b.N = 2000000
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
}
func BenchmarkPop(b *testing.B) {
s := New()
b.N = 2000000
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Pop()
}
}
func BenchmarkGodsPop(b *testing.B) {
s := arraystack.New()
b.N = 2000000
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Pop()
}
}
func BenchmarkValues(b *testing.B) {
s := New()
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Values()
}
}
func BenchmarkGodsValues(b *testing.B) {
s := arraystack.New()
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Values()
}
}

108
list/list.go Normal file
View File

@@ -0,0 +1,108 @@
package list
type Node struct {
next *Node
value interface{}
}
func (node *Node) Value() interface{} {
return node.value
}
type List struct {
head *Node
size uint
}
func New() *List {
return &List{}
}
func (l *List) Size() uint {
return l.size
}
func (l *List) Push(v interface{}) {
l.size++
if l.head == nil {
l.head = &Node{value: v}
return
}
l.head = &Node{value: v, next: l.head}
}
func (l *List) PushNode(n *Node) {
l.size++
if l.head == nil {
l.head = n
return
}
n.next = l.head
l.head = n
}
func (l *List) Pop() (result interface{}, found bool) {
if n, ok := l.PopNode(); ok {
return n.value, ok
}
return nil, false
}
func (l *List) PopNode() (result *Node, found bool) {
if l.head == nil {
return nil, false
}
result = l.head
found = true
l.head = result.next
result.next = nil
l.size--
return
}
func (l *List) Remove(idx uint) (result *Node, found bool) {
if l.size == 0 {
return nil, false
}
if idx == 0 {
result = l.head
found = true
l.head = result.next
result.next = nil
l.size--
return
}
for cur := l.head; cur.next != nil; cur = cur.next {
if idx == 1 {
l.size--
result = cur.next
found = true
cur.next = result.next
result.next = nil
return
}
idx--
}
return nil, false
}
func (l *List) Values() (result []interface{}) {
l.Traversal(func(cur *Node) bool {
result = append(result, cur.value)
return true
})
return
}
func (l *List) Traversal(every func(*Node) bool) {
for cur := l.head; cur != nil; cur = cur.next {
if !every(cur) {
break
}
}
}

87
list/list_test.go Normal file
View File

@@ -0,0 +1,87 @@
package list
import (
"testing"
"github.com/davecgh/go-spew/spew"
)
func TestPush(t *testing.T) {
l := New()
for i := 0; i < 5; i++ {
l.Push(i)
}
var result string
result = spew.Sprint(l.Values())
if result != "[4 3 2 1 0]" {
t.Error(result)
}
l.Push(0)
result = spew.Sprint(l.Values())
if result != "[0 4 3 2 1 0]" {
t.Error(result)
}
}
func TestPop(t *testing.T) {
l := New()
for i := 0; i < 5; i++ {
l.Push(i)
}
if v, ok := l.Pop(); ok {
if v != 4 {
t.Error(v)
}
} else {
t.Error("Pop should ok, but is not ok")
}
var result string
result = spew.Sprint(l.Values())
if result != "[3 2 1 0]" {
t.Error(result)
}
for i := 3; l.Size() != 0; i-- {
if v, ok := l.Pop(); ok {
if v != i {
t.Error(i, v, "is not equals")
}
} else {
t.Error("Pop should ok, but is not ok", i)
}
}
l.Push(0)
result = spew.Sprint(l.Values())
if result != "[0]" {
t.Error(result)
}
if l.Size() != 1 {
t.Error("l.Size() == 1, but is error, size = ", l.Size())
}
}
func TestRemove(t *testing.T) {
l := New()
for i := 0; i < 5; i++ {
l.Push(i)
}
for i := 0; i < 5; i++ {
if n, ok := l.Remove(0); ok {
if n.Value() != 4-i {
t.Error(n)
}
} else {
t.Error("Pop should ok, but is not ok", i)
}
}
if l.Size() != 0 {
t.Error("l.Size() == 0, but is error, size = ", l.Size())
}
}

63
map/hashmap/hashmap.go Normal file
View File

@@ -0,0 +1,63 @@
package hashmap
import "fmt"
type HashMap struct {
hm map[interface{}]interface{}
}
// New instantiates a hash map.
func New() *HashMap {
return &HashMap{hm: make(map[interface{}]interface{})}
}
// Put inserts element into the map.
func (hm *HashMap) Put(key interface{}, value interface{}) {
hm.hm[key] = value
}
func (hm *HashMap) Get(key interface{}) (value interface{}, isfound bool) {
value, isfound = hm.hm[key]
return
}
func (hm *HashMap) Remove(key interface{}) {
delete(hm.hm, key)
}
func (hm *HashMap) Empty() bool {
return len(hm.hm) == 0
}
func (hm *HashMap) Size() int {
return len(hm.hm)
}
func (hm *HashMap) Keys() []interface{} {
keys := make([]interface{}, len(hm.hm))
count := 0
for key := range hm.hm {
keys[count] = key
count++
}
return keys
}
func (hm *HashMap) Values() []interface{} {
values := make([]interface{}, len(hm.hm))
count := 0
for _, value := range hm.hm {
values[count] = value
count++
}
return values
}
func (hm *HashMap) Clear() {
hm.hm = make(map[interface{}]interface{})
}
func (hm *HashMap) String() string {
str := fmt.Sprintf("%v", hm.hm)
return str
}

118
map/hashmap/hashmap_test.go Normal file
View File

@@ -0,0 +1,118 @@
package hashmap
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
)
func loadTestData() []int {
log.SetFlags(log.Lshortfile)
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 TestCount(t *testing.T) {
hm := New()
// for i := 0; i < 100000; i++ {
// hm.Put(i, i)
// }
for i := 0; i < 100000; i++ {
hm.Put(i, i)
}
// t.Error(hm.Get(4))
}
var executeCount = 5
var compareSize = 100000
func BenchmarkPut(b *testing.B) {
b.StopTimer()
l := loadTestData()
hm := New()
b.N = len(l) * executeCount
// for i := 0; i < len(l); i++ {
// v := l[i]
// hm.Put(v, v)
// }
b.StartTimer()
for c := 0; c < executeCount; c++ {
for i := 0; i < len(l); i++ {
v := l[i]
hm.Put(v, v)
}
}
//b.Log(len(hm.table), hm.size)
//PrintMemUsage()
}
func BenchmarkGoPut(b *testing.B) {
l := loadTestData()
hm := make(map[int]int)
b.N = len(l) * executeCount
for c := 0; c < executeCount; c++ {
for i := 0; i < len(l); i++ {
v := l[i]
hm[v] = v
}
}
//b.Log(len(m))
//PrintMemUsage()
}
// func BenchmarkGet(b *testing.B) {
// b.StopTimer()
// l := loadTestData()
// hm := New()
// b.N = len(l) * executeCount
// for i := 0; i < len(l); i++ {
// v := l[i]
// hm.Put(v, v)
// }
// b.StartTimer()
// for i := 0; i < b.N; i++ {
// hm.Get(i)
// }
// //b.Log(len(hm.table), hm.size)
// //PrintMemUsage()
// }
// func BenchmarkGoGet(b *testing.B) {
// b.StopTimer()
// l := loadTestData()
// hm := make(map[int]int)
// b.N = len(l) * executeCount
// for i := 0; i < len(l); i++ {
// v := l[i]
// hm[v] = v
// }
// b.StartTimer()
// for i := 0; i < b.N; i++ {
// if _, ok := hm[i]; !ok {
// }
// }
// //b.Log(len(m))
// //PrintMemUsage()
// }

87
priority_list/iterator.go Normal file
View File

@@ -0,0 +1,87 @@
package plist
type Iterator struct {
pl *PriorityList
cur *Node
}
func (iter *Iterator) Value() interface{} {
return iter.cur.value
}
func (iter *Iterator) Prev() bool {
if iter.cur == iter.pl.head {
return false
}
iter.cur = iter.cur.prev
return iter.cur != iter.pl.head
}
func (iter *Iterator) Next() bool {
if iter.cur == iter.pl.tail {
return false
}
iter.cur = iter.cur.next
return iter.cur != iter.pl.tail
}
func (iter *Iterator) MoveToHead() {
iter.cur = iter.pl.head
}
func (iter *Iterator) MoveToTail() {
iter.cur = iter.pl.tail
}
type CircularIterator struct {
pl *PriorityList
cur *Node
}
func (iter *CircularIterator) Value() interface{} {
return iter.cur.value
}
func (iter *CircularIterator) Prev() bool {
if iter.pl.size == 0 {
return false
}
if iter.cur == iter.pl.head {
iter.cur = iter.pl.tail.prev
return true
}
iter.cur = iter.cur.prev
if iter.cur == iter.pl.head {
iter.cur = iter.pl.tail.prev
}
return true
}
func (iter *CircularIterator) Next() bool {
if iter.pl.size == 0 {
return false
}
if iter.cur == iter.pl.tail {
iter.cur = iter.pl.head.next
return true
}
iter.cur = iter.cur.next
if iter.cur == iter.pl.tail {
iter.cur = iter.pl.head.next
}
return true
}
func (iter *CircularIterator) MoveToHead() {
iter.cur = iter.pl.head
}
func (iter *CircularIterator) MoveToTail() {
iter.cur = iter.pl.tail
}

View File

@@ -0,0 +1,165 @@
package plist
import (
"strings"
"474420502.top/eson/structure/compare"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
prev, next *Node
value interface{}
}
type PriorityList struct {
head, tail *Node
size int
Compare compare.Compare
}
func New(Compare compare.Compare) *PriorityList {
pl := &PriorityList{head: &Node{}, tail: &Node{}, size: 0, Compare: Compare}
pl.head.next = pl.tail
pl.tail.prev = pl.head
return pl
}
func (pl *PriorityList) String() string {
content := ""
cur := pl.head.next
for ; cur != pl.tail; cur = cur.next {
content += spew.Sprint(cur.value) + " "
}
content = strings.TrimRight(content, " ")
return content
}
func (pl *PriorityList) RString() string {
content := ""
cur := pl.tail.prev
for ; cur != pl.head; cur = cur.prev {
content += spew.Sprint(cur.value) + " "
}
content = strings.TrimRight(content, " ")
return content
}
func (pl *PriorityList) Iterator() *Iterator {
return &Iterator{pl: pl, cur: pl.head}
}
func (pl *PriorityList) CircularIterator() *CircularIterator {
return &CircularIterator{pl: pl, cur: pl.head}
}
func (pl *PriorityList) Size() int {
return pl.size
}
func (pl *PriorityList) Push(value interface{}) {
pl.size++
pnode := &Node{value: value}
if pl.size == 1 {
pl.head.next = pnode
pl.tail.prev = pnode
pnode.prev = pl.head
pnode.next = pl.tail
return
}
cur := pl.head
for ; cur.next != pl.tail; cur = cur.next {
if pl.Compare(value, cur.next.value) > 0 {
cnext := cur.next
cur.next = pnode
cnext.prev = pnode
pnode.prev = cur
pnode.next = cnext
return
}
}
cur.next = pnode
pnode.prev = cur
pnode.next = pl.tail
pl.tail.prev = pnode
}
func (pl *PriorityList) Top() (result interface{}, ok bool) {
if pl.size > 0 {
return pl.head.next.value, true
}
return nil, false
}
func (pl *PriorityList) Pop() (result interface{}, ok bool) {
if pl.size > 0 {
pl.size--
temp := pl.head.next
temp.next.prev = pl.head
pl.head.next = temp.next
return temp.value, true
}
return nil, false
}
func (pl *PriorityList) Get(idx int) (interface{}, bool) {
if n, ok := pl.GetNode(idx); ok {
return n.value, true
}
return nil, false
}
func (pl *PriorityList) GetNode(idx int) (*Node, bool) {
if idx >= 0 {
cur := pl.head.next
for i := 0; cur != pl.tail; i++ {
if i == idx {
return cur, true
}
cur = cur.next
}
} else {
cur := pl.tail.prev
for i := -1; cur != pl.head; i-- {
if i == idx {
return cur, true
}
cur = cur.prev
}
}
return nil, false
}
func (pl *PriorityList) RemoveWithIndex(idx int) {
if n, ok := pl.GetNode(idx); ok {
pl.Remove(n)
}
}
func (pl *PriorityList) Remove(node *Node) {
prev := node.prev
next := node.next
prev.next = next
next.prev = prev
node.prev = nil
node.next = nil
pl.size--
}
func (pl *PriorityList) Values() []interface{} {
values := make([]interface{}, pl.size, pl.size)
for i, cur := 0, pl.head.next; cur != pl.tail; i, cur = i+1, cur.next {
values[i] = cur.value
}
return values
}

View File

@@ -0,0 +1,260 @@
package plist
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"474420502.top/eson/structure/compare"
)
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 TestInsert(t *testing.T) {
pl := New(compare.Int)
for i := 0; i < 10; i++ {
pl.Push(i)
}
if pl.size != 10 {
t.Error(pl.size)
}
if pl.String() != "9 8 7 6 5 4 3 2 1 0" {
t.Error(pl.String())
}
if pl.RString() != "0 1 2 3 4 5 6 7 8 9" {
t.Error(pl.RString())
}
for i := 0; i < 10; i++ {
pl.Push(i)
}
if pl.String() != "9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0" {
t.Error(pl.String())
}
if pl.RString() != "0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9" {
t.Error(pl.RString())
}
}
func TestIterator(t *testing.T) {
pl := New(compare.Int)
for i := 0; i < 10; i++ {
pl.Push(i)
}
iter := pl.Iterator()
for i := 0; iter.Next(); i++ {
if iter.Value() != 9-i {
t.Error("iter.Next() ", iter.Value(), "is not equal ", 9-i)
}
}
if iter.cur != iter.pl.tail {
t.Error("current point is not equal tail ", iter.pl.tail)
}
for i := 0; iter.Prev(); i++ {
if iter.Value() != i {
t.Error("iter.Prev() ", iter.Value(), "is not equal ", i)
}
}
}
func TestCircularIterator(t *testing.T) {
pl := New(compare.Int)
for i := 0; i < 10; i++ {
pl.Push(i)
}
iter := pl.CircularIterator()
for i := 0; i != 10; i++ {
iter.Next()
if iter.Value() != 9-i {
t.Error("iter.Next() ", iter.Value(), "is not equal ", 9-i)
}
}
if iter.cur != iter.pl.tail.prev {
t.Error("current point is not equal tail ", iter.pl.tail.prev)
}
if iter.Next() {
if iter.Value() != 9 {
t.Error("iter.Value() != ", iter.Value())
}
}
iter.MoveToTail()
for i := 0; i != 10; i++ {
iter.Prev()
if iter.Value() != i {
t.Error("iter.Prev() ", iter.Value(), "is not equal ", i)
}
}
if iter.cur != iter.pl.head.next {
t.Error("current point is not equal tail ", iter.pl.tail.prev)
}
if iter.Prev() {
if iter.Value() != 0 {
t.Error("iter.Value() != ", iter.Value())
}
}
}
func TestGet(t *testing.T) {
pl := New(compare.Int)
for i := 0; i < 10; i++ {
pl.Push(i)
}
for _, v := range []int{0, 9, 5, 7} {
if g, ok := pl.Get(v); ok {
if g != (9 - v) {
t.Error(v, "Get == ", g)
}
}
}
if n, ok := pl.Get(10); ok {
t.Error("index 10 is over size", n)
}
}
func TestTop(t *testing.T) {
pl := New(compare.Int)
for i := 0; i < 10; i++ {
pl.Push(i)
}
i := 0
for n, ok := pl.Pop(); ok; n, ok = pl.Pop() {
if (9 - i) != n {
t.Error("value is not equal ", i)
}
if top, tok := pl.Top(); tok {
if (9 - i - 1) != top {
t.Error("top is error cur i = ", i, "top is ", top)
}
}
i++
}
if pl.Size() != 0 {
t.Error("list size is not zero")
}
}
func TestPop(t *testing.T) {
pl := New(compare.Int)
for i := 0; i < 10; i++ {
pl.Push(i)
}
i := 0
for n, ok := pl.Pop(); ok; n, ok = pl.Pop() {
if (9 - i) != n {
t.Error("value is not equal ", i)
}
i++
}
if pl.Size() != 0 {
t.Error("list size is not zero")
}
for i := 9; i >= 0; i-- {
pl.Push(i)
}
i = 0
for n, ok := pl.Pop(); ok; n, ok = pl.Pop() {
if (9 - i) != n {
t.Error("value is not equal ", i)
}
i++
}
if pl.Size() != 0 {
t.Error("list size is not zero")
}
}
func TestRemove(t *testing.T) {
pl := New(compare.Int)
for i := 0; i < 10; i++ {
pl.Push(i)
}
pl.RemoveWithIndex(0)
if g, ok := pl.Get(0); ok {
if g != 8 {
t.Error(g)
}
}
pl.RemoveWithIndex(-1)
if g, ok := pl.Get(-1); ok {
if g != 1 {
t.Error(g)
}
}
}
func BenchmarkGet(b *testing.B) {
pl := New(compare.Int)
l := loadTestData()
for _, v := range l {
pl.Push(v)
}
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for i := 0; i < b.N; i++ {
if i%2 == 0 {
pl.Get(i)
}
}
}
func BenchmarkInsert(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 1
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
pl := New(compare.Int)
for _, v := range l {
pl.Push(v)
}
}
}

230
priority_queue/iterator.go Normal file
View File

@@ -0,0 +1,230 @@
package pqueue
import (
"474420502.top/eson/structure/lastack"
)
type Iterator struct {
dir int
up *Node
cur *Node
tstack *lastack.Stack
// curnext *Node
}
func initIterator(avltree *vbTree) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = avltree.root
return iter
}
func NewIterator(n *Node) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = n
return iter
}
func NewIteratorWithCap(n *Node, cap int) *Iterator {
iter := &Iterator{tstack: lastack.NewWithCap(cap)}
iter.up = n
return iter
}
func (iter *Iterator) SeNode(n *Node) {
iter.up = n
iter.dir = 0
iter.tstack.Clear()
}
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) GetNext(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SeNode(cur)
iter.curPushNextStack(iter.up)
iter.up = iter.getNextUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getNextUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushNextStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Next() (result bool) {
if iter.dir > -1 {
if iter.dir == 1 && iter.cur != nil {
iter.tstack.Clear()
iter.curPushNextStack(iter.cur)
iter.up = iter.getNextUp(iter.cur)
}
iter.dir = -1
}
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
}
return false
}
func (iter *Iterator) GetPrev(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SeNode(cur)
iter.curPushPrevStack(iter.up)
iter.up = iter.getPrevUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushPrevStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Prev() (result bool) {
if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev)
if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈
iter.tstack.Clear()
iter.curPushPrevStack(iter.cur) // 把当前cur计算的逆向回朔
iter.up = iter.getPrevUp(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.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
iter.curPushPrevStack(iter.cur)
return true
}
// 如果再次计算的栈为空, 则只能返回false
return false
}
func getRelationship(cur *Node) int {
if cur.parent.children[1] == cur {
return 1
}
return 0
}
func (iter *Iterator) getPrevUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushPrevStack(cur *Node) {
Prev := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值
if Prev != nil {
iter.tstack.Push(Prev)
for Prev.children[1] != nil {
Prev = Prev.children[1]
iter.tstack.Push(Prev) // 入栈 用于回溯
}
}
}
func (iter *Iterator) getNextUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushNextStack(cur *Node) {
next := cur.children[1]
if next != nil {
iter.tstack.Push(next)
for next.children[0] != nil {
next = next.children[0]
iter.tstack.Push(next)
}
}
}

View File

@@ -0,0 +1,80 @@
package pqueue
import "474420502.top/eson/structure/compare"
type PriorityQueue struct {
queue *vbTree
}
func (pq *PriorityQueue) Iterator() *Iterator {
return NewIterator(pq.queue.top)
}
func New(Compare compare.Compare) *PriorityQueue {
return &PriorityQueue{queue: newVBT(Compare)}
}
func (pq *PriorityQueue) Size() int {
return pq.queue.Size()
}
func (pq *PriorityQueue) Push(value interface{}) {
pq.queue.Put(value)
}
func (pq *PriorityQueue) Top() (result interface{}, ok bool) {
if pq.queue.top != nil {
return pq.queue.top.value, true
}
return nil, false
}
func (pq *PriorityQueue) Pop() (result interface{}, ok bool) {
if pq.queue.top != nil {
result = pq.queue.top.value
pq.queue.removeNode(pq.queue.top)
return result, true
}
return nil, false
}
func (pq *PriorityQueue) Index(idx int) (interface{}, bool) {
return pq.queue.Index(idx)
}
func (pq *PriorityQueue) IndexNode(idx int) (*Node, bool) {
n := pq.queue.indexNode(idx)
return n, n != nil
}
func (pq *PriorityQueue) Get(key interface{}) (interface{}, bool) {
return pq.queue.Get(key)
}
func (pq *PriorityQueue) GetNode(key interface{}) (*Node, bool) {
return pq.queue.GetNode(key)
}
func (pq *PriorityQueue) GetAround(key interface{}) [3]interface{} {
return pq.queue.GetAround(key)
}
func (pq *PriorityQueue) GetAroundNode(key interface{}) [3]*Node {
return pq.queue.getArounNode(key)
}
func (pq *PriorityQueue) GetRange(k1, k2 interface{}) []interface{} {
return pq.queue.GetRange(k1, k2)
}
func (pq *PriorityQueue) RemoveIndex(idx int) (interface{}, bool) {
return pq.queue.RemoveIndex(idx)
}
func (pq *PriorityQueue) Remove(key interface{}) (interface{}, bool) {
return pq.queue.Remove(key)
}
func (pq *PriorityQueue) Values() []interface{} {
return pq.queue.Values()
}

View File

@@ -0,0 +1,347 @@
package pqueue
import (
"testing"
"github.com/davecgh/go-spew/spew"
"474420502.top/eson/structure/compare"
)
func TestQueuePush(t *testing.T) {
pq := New(compare.Int)
for _, v := range []int{32, 10, 53, 78, 90, 1, 4} {
pq.Push(v)
if v, ok := pq.Top(); ok {
} else {
t.Error(v)
}
}
if v, ok := pq.Top(); ok {
if v != 90 {
t.Error(v)
}
} else {
t.Error(v)
}
}
func TestQueuePop(t *testing.T) {
pq := New(compare.Int)
for _, v := range []int{32, 10, 53, 78, 90, 1, 4} {
pq.Push(v)
if v, ok := pq.Top(); ok {
} else {
t.Error(v)
}
}
l := []int{90, 78, 53, 32, 10, 4, 1}
for _, lv := range l {
if v, ok := pq.Pop(); ok {
if v != lv {
t.Error(v)
}
} else {
t.Error(v)
}
}
if v, ok := pq.Pop(); ok {
t.Error(v)
}
}
func TestQueueGet(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v)
}
if v, ok := pq.Get(0); ok {
t.Error(v)
}
if v, ok := pq.Get(70); ok {
t.Error(v)
}
for _, v := range l {
if gv, ok := pq.Get(v); ok {
if gv != v {
t.Error("Get value is error, value is", gv)
}
}
}
}
func TestQueueGetRange(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v)
}
var result string
result = spew.Sprint(pq.GetRange(10, 40))
if result != "[10 32]" {
t.Error(result)
}
result = spew.Sprint(pq.GetRange(1, 90))
if result != "[1 4 10 32 53 78 90]" {
t.Error(result)
}
result = spew.Sprint(pq.GetRange(0, 90))
if result != "[1 4 10 32 53 78 90]" {
t.Error(result)
}
result = spew.Sprint(pq.GetRange(1, 100))
if result != "[1 4 10 32 53 78 90]" {
t.Error(result)
}
result = spew.Sprint(pq.GetRange(5, 88))
if result != "[10 32 53 78]" {
t.Error(result)
}
}
func TestQueueGetAround(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v)
}
var result string
result = spew.Sprint(pq.GetAround(53))
if result != "[32 53 78]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(52))
if result != "[32 <nil> 53]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(1))
if result != "[<nil> 1 4]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(90))
if result != "[78 90 <nil>]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(0))
if result != "[<nil> <nil> 1]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(100))
if result != "[90 <nil> <nil>]" {
t.Error(result)
}
}
func TestQueueRemove(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v)
}
content := ""
for _, v := range l {
pq.Remove(v)
content += spew.Sprint(pq.Values())
}
if content != "[1 4 10 53 78 90][1 4 53 78 90][1 4 78 90][1 4 90][1 4][4][]" {
t.Error(content)
}
}
func TestQueueRemoveIndex(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v)
}
content := ""
for range l {
pq.RemoveIndex(0)
content += spew.Sprint(pq.Values())
}
if content != "[1 4 10 32 53 78][1 4 10 32 53][1 4 10 32][1 4 10][1 4][1][]" {
t.Error(content)
}
if n, ok := pq.RemoveIndex(0); ok {
t.Error("pq is not exist elements", n)
}
}
func TestQueueIndex(t *testing.T) {
pq := New(compare.Int)
for _, v := range []int{32, 10, 53, 78, 90, 1, 4} {
pq.Push(v)
}
l := []int{90, 78, 53, 32, 10, 4, 1}
for i, lv := range l {
if v, ok := pq.Index(len(l) - i - 1); ok {
if v != l[len(l)-i-1] {
t.Error(v)
}
} else {
t.Error(i, "index is not exist")
}
if v, ok := pq.Index(i); ok {
if v != lv {
t.Error(v)
}
} else {
t.Error(i, "index is not exist")
}
}
if v, ok := pq.Index(-1); ok {
if v != 1 {
t.Error(v)
}
} else {
t.Error("-1 index is not exist")
}
if v, ok := pq.Index(pq.Size()); ok {
t.Error("index is exits", pq.Size(), v)
}
if v, ok := pq.Index(pq.Size() - 1); !ok {
if v != 1 {
t.Error("the last value is 1 not is ", v)
}
}
if v, ok := pq.Index(-10); ok {
t.Error("-10 index is exits", v)
}
}
func BenchmarkQueueGet(b *testing.B) {
l := loadTestData()
pq := New(compare.Int)
for _, v := range l {
pq.Push(v)
}
execCount := 5
b.N = len(l) * execCount
b.ResetTimer()
b.StartTimer()
ALL:
for i := 0; i < execCount; i++ {
for _, v := range l {
if gv, ok := pq.Get(v); !ok {
b.Error(gv)
break ALL
}
}
}
}
func BenchmarkQueueRemove(b *testing.B) {
l := loadTestData()
pq := New(compare.Int)
for _, v := range l {
pq.Push(v)
}
b.N = len(l)
b.ResetTimer()
b.StartTimer()
for _, v := range l {
pq.Remove(v)
}
}
func BenchmarkQueueIndex(b *testing.B) {
l := loadTestData()
pq := New(compare.Int)
for _, v := range l {
pq.Push(v)
}
execCount := 2
b.N = len(l) * execCount
b.ResetTimer()
b.StartTimer()
ALL:
for i := 0; i < execCount; i++ {
for idx := range l {
if v, ok := pq.Index(idx); !ok {
b.Error(v)
break ALL
}
}
}
}
func BenchmarkPriorityPush(b *testing.B) {
l := loadTestData()
execCount := 5
b.N = len(l) * execCount
b.ResetTimer()
b.StartTimer()
for i := 0; i < execCount; i++ {
pq := New(compare.Int)
for _, v := range l {
pq.Push(v)
}
}
}
func BenchmarkPriorityPop(b *testing.B) {
l := loadTestData()
pq := New(compare.Int)
for _, v := range l {
pq.Push(v)
}
b.N = len(l)
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
pq.Pop()
}
}

981
priority_queue/vbt.go Normal file
View File

@@ -0,0 +1,981 @@
package pqueue
import (
"474420502.top/eson/structure/compare"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
children [2]*Node
parent *Node
size int
value interface{}
}
func (n *Node) String() string {
if n == nil {
return "nil"
}
p := "nil"
if n.parent != nil {
p = spew.Sprint(n.parent.value)
}
return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.size) + ")"
}
type vbTree struct {
root *Node
Compare compare.Compare
top *Node
iter *Iterator
}
func newVBT(Compare compare.Compare) *vbTree {
return &vbTree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)}
}
func (tree *vbTree) String() string {
str := "AVLTree\n"
if tree.root == nil {
return str + "nil"
}
output(tree.root, "", true, &str)
return str
}
func (tree *vbTree) Iterator() *Iterator {
return initIterator(tree)
}
func (tree *vbTree) Size() int {
if tree.root == nil {
return 0
}
return tree.root.size
}
func (tree *vbTree) indexNode(idx int) *Node {
cur := tree.root
if idx >= 0 {
for cur != nil {
rs := getSize(cur.children[1])
if idx == rs {
return cur
} else if idx < rs {
cur = cur.children[1]
} else {
idx = idx - rs - 1
cur = cur.children[0]
}
}
} else {
idx = -idx - 1
for cur != nil {
ls := getSize(cur.children[0])
if idx == ls {
return cur
} else if idx < ls {
cur = cur.children[0]
} else {
idx = idx - ls - 1
cur = cur.children[1]
}
}
}
return nil
}
func (tree *vbTree) Index(idx int) (interface{}, bool) {
n := tree.indexNode(idx)
if n != nil {
return n.value, true
}
return nil, false
}
func (tree *vbTree) IndexRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1
if idx1^idx2 < 0 {
if idx1 < 0 {
idx1 = tree.root.size + idx1 - 1
} else {
idx2 = tree.root.size + idx2 - 1
}
}
if idx1 > idx2 {
ok = true
if idx1 >= tree.root.size {
idx1 = tree.root.size - 1
ok = false
}
n := tree.indexNode(idx1)
tree.iter.SeNode(n)
iter := tree.iter
result = make([]interface{}, 0, idx1-idx2)
for i := idx2; i <= idx1; i++ {
if iter.Next() {
result = append(result, iter.Value())
} else {
ok = false
return
}
}
return
} else {
ok = true
if idx2 >= tree.root.size {
idx2 = tree.root.size - 1
ok = false
}
if n := tree.indexNode(idx1); n != nil {
tree.iter.SeNode(n)
iter := tree.iter
result = make([]interface{}, 0, idx2-idx1)
for i := idx1; i <= idx2; i++ {
if iter.Prev() {
result = append(result, iter.Value())
} else {
ok = false
return
}
}
return
}
}
return nil, false
}
func (tree *vbTree) RemoveIndex(idx int) (interface{}, bool) {
n := tree.indexNode(idx)
if n != nil {
tree.removeNode(n)
return n.value, true
}
return nil, false
}
func (tree *vbTree) removeNode(n *Node) {
if tree.root.size == 1 {
tree.root = nil
tree.top = nil
// return n
return
}
if tree.top == n {
tree.top = tree.iter.GetPrev(n, 1)
}
ls, rs := getChildrenSize(n)
if ls == 0 && rs == 0 {
p := n.parent
p.children[getRelationship(n)] = nil
tree.fixSizeWithRemove(p)
// return n
return
}
var cur *Node
if ls > rs {
cur = n.children[0]
for cur.children[1] != nil {
cur = cur.children[1]
}
cleft := cur.children[0]
cur.parent.children[getRelationship(cur)] = cleft
if cleft != nil {
cleft.parent = cur.parent
}
} else {
cur = n.children[1]
for cur.children[0] != nil {
cur = cur.children[0]
}
cright := cur.children[1]
cur.parent.children[getRelationship(cur)] = cright
if cright != nil {
cright.parent = cur.parent
}
}
cparent := cur.parent
// 修改为interface 交换
// n.value, cur.value = cur.value, n.value
tree.replace(n, cur)
// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
if cparent == n {
tree.fixSizeWithRemove(cur)
} else {
tree.fixSizeWithRemove(cparent)
}
// return cur
return
}
func (tree *vbTree) Remove(key interface{}) (interface{}, bool) {
if n, ok := tree.GetNode(key); ok {
tree.removeNode(n)
return n.value, true
}
// return nil
return nil, false
}
// Values 返回先序遍历的值
func (tree *vbTree) Values() []interface{} {
mszie := 0
if tree.root != nil {
mszie = tree.root.size
}
result := make([]interface{}, 0, mszie)
tree.Traversal(func(v interface{}) bool {
result = append(result, v)
return true
}, LDR)
return result
}
func (tree *vbTree) GetRange(k1, k2 interface{}) (result []interface{}) {
c := tree.Compare(k2, k1)
switch c {
case 1:
var min, max *Node
resultmin := tree.getArounNode(k1)
resultmax := tree.getArounNode(k2)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if max == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
// iter := NewIterator(min)
tree.iter.SeNode(min)
iter := tree.iter
for iter.Next() {
result = append(result, iter.Value())
if iter.cur == max {
break
}
}
case -1:
var min, max *Node
resultmin := tree.getArounNode(k2)
resultmax := tree.getArounNode(k1)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if min == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
// iter := NewIterator(max)
tree.iter.SeNode(max)
iter := tree.iter
for iter.Prev() {
result = append(result, iter.Value())
if iter.cur == min {
break
}
}
case 0:
if n, ok := tree.GetNode(k1); ok {
return []interface{}{n.value}
}
return []interface{}{}
}
return
}
func (tree *vbTree) Get(key interface{}) (interface{}, bool) {
n, ok := tree.GetNode(key)
if ok {
return n.value, true
}
return n, false
}
func (tree *vbTree) GetAround(key interface{}) (result [3]interface{}) {
an := tree.getArounNode(key)
for i, n := range an {
if n != nil {
result[i] = n.value
}
}
return
}
func (tree *vbTree) getArounNode(key interface{}) (result [3]*Node) {
var last *Node
var lastc int
for n := tree.root; n != nil; {
last = n
c := tree.Compare(key, n.value)
switch c {
case -1:
n = n.children[0]
lastc = c
case 1:
n = n.children[1]
lastc = c
case 0:
tree.iter.SeNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.value, n.value) == 0 {
n = iter.cur
} else {
break
}
}
result[1] = n
n = nil
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
switch lastc {
case 1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[0] = last
result[2] = tree.iter.GetNext(last, 1)
}
case -1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[2] = last
result[0] = tree.iter.GetPrev(last, 1)
}
case 0:
if result[1] == nil {
return
}
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
}
return
}
func (tree *vbTree) GetNode(value interface{}) (*Node, bool) {
for n := tree.root; n != nil; {
switch c := tree.Compare(value, n.value); c {
case -1:
n = n.children[0]
case 1:
n = n.children[1]
case 0:
tree.iter.SeNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.value, n.value) == 0 {
n = iter.cur
} else {
break
}
}
return n, true
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
return nil, false
}
func (tree *vbTree) Put(key interface{}) {
Node := &Node{value: key, size: 1}
if tree.root == nil {
tree.root = Node
tree.top = Node
return
}
if tree.Compare(key, tree.top.value) > 0 {
tree.top = Node
}
for cur := tree.root; ; {
if cur.size > 8 {
factor := cur.size / 10 // or factor = 1
ls, rs := cur.children[0].size, cur.children[1].size
if rs >= ls*2+factor || ls >= rs*2+factor {
cur = tree.fixSize(cur, ls, rs)
}
}
cur.size++
c := tree.Compare(key, cur.value)
if c < 0 {
if cur.children[0] == nil {
cur.children[0] = Node
Node.parent = cur
if cur.parent != nil && cur.parent.size == 3 {
if cur.parent.children[0] == nil {
tree.lrrotate3(cur.parent)
} else {
tree.rrotate3(cur.parent)
}
}
return
}
cur = cur.children[0]
} else {
if cur.children[1] == nil {
cur.children[1] = Node
Node.parent = cur
if cur.parent != nil && cur.parent.size == 3 {
if cur.parent.children[1] == nil {
tree.rlrotate3(cur.parent)
} else {
tree.lrotate3(cur.parent)
}
}
return
}
cur = cur.children[1]
}
}
}
type TraversalMethod int
const (
// L = left R = right D = Value(dest)
_ TraversalMethod = iota
//DLR 先值 然后左递归 右递归 下面同理
DLR
//LDR 先从左边有序访问到右边 从小到大
LDR
// LRD 同理
LRD
// DRL 同理
DRL
// RDL 先从右边有序访问到左边 从大到小
RDL
// RLD 同理
RLD
)
// Traversal 遍历的方法 默认是LDR 从小到大 Compare 为 l < r
func (tree *vbTree) Traversal(every func(v interface{}) bool, traversalMethod ...interface{}) {
if tree.root == nil {
return
}
method := LDR
if len(traversalMethod) != 0 {
method = traversalMethod[0].(TraversalMethod)
}
switch method {
case DLR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LDR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LRD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
case DRL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case RDL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
return true
}
traverasl(tree.root)
case RLD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
}
}
func setChildNotNil(cur *Node, cidx int, child *Node) {
cur.children[cidx] = child
cur.children[cidx].parent = cur
}
func setChild(cur *Node, cidx int, child *Node) {
cur.children[cidx] = child
if child != nil {
cur.children[cidx].parent = cur
}
}
func (tree *vbTree) replace(old, new *Node) {
setChild(new, 0, old.children[0])
setChild(new, 1, old.children[1])
if old.parent == nil {
tree.root = new
} else {
if old.parent.children[1] == old {
old.parent.children[1] = new
} else {
old.parent.children[0] = new
}
}
new.size = old.size
new.parent = old.parent
}
func (tree *vbTree) takeParent(token, person *Node) {
if token.parent == nil {
tree.root = person
} else {
if token.parent.children[1] == token {
token.parent.children[1] = person
} else {
token.parent.children[0] = person
}
}
person.parent = token.parent
}
func (tree *vbTree) lrrotate3(cur *Node) *Node {
const l = 1
const r = 0
ln := cur.children[l]
cur.children[l] = nil
lrn := ln.children[r]
ln.children[r] = nil
tree.takeParent(cur, lrn)
setChildNotNil(lrn, l, ln)
setChildNotNil(lrn, r, cur)
lrn.size = 3
lrn.children[l].size = 1
lrn.children[r].size = 1
return lrn
}
func (tree *vbTree) lrrotate(cur *Node) *Node {
const l = 1
const r = 0
ln := cur.children[l]
lrn := ln.children[r]
lrln := lrn.children[l]
lrrn := lrn.children[r]
tree.takeParent(cur, lrn)
setChild(ln, r, lrln)
setChild(cur, l, lrrn)
setChildNotNil(lrn, l, ln)
setChildNotNil(lrn, r, cur)
ln.size = getChildrenSumSize(ln) + 1
cur.size = getChildrenSumSize(cur) + 1
lrn.size = getChildrenSumSize(lrn) + 1
return lrn
}
func (tree *vbTree) rlrotate3(cur *Node) *Node {
const l = 0
const r = 1
ln := cur.children[l]
cur.children[l] = nil
lrn := ln.children[r]
ln.children[r] = nil
tree.takeParent(cur, lrn)
setChildNotNil(lrn, l, ln)
setChildNotNil(lrn, r, cur)
lrn.size = 3
lrn.children[l].size = 1
lrn.children[r].size = 1
return lrn
}
func (tree *vbTree) rlrotate(cur *Node) *Node {
const l = 0
const r = 1
ln := cur.children[l]
lrn := ln.children[r]
lrln := lrn.children[l]
lrrn := lrn.children[r]
tree.takeParent(cur, lrn)
setChild(ln, r, lrln)
setChild(cur, l, lrrn)
setChildNotNil(lrn, l, ln)
setChildNotNil(lrn, r, cur)
ln.size = getChildrenSumSize(ln) + 1
cur.size = getChildrenSumSize(cur) + 1
lrn.size = getChildrenSumSize(lrn) + 1
return lrn
}
func (tree *vbTree) rrotate3(cur *Node) *Node {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
cur.children[l] = nil
tree.takeParent(cur, mov)
setChildNotNil(mov, r, cur)
mov.size = 3
cur.size = 1
return mov
}
func (tree *vbTree) rrotate(cur *Node) *Node {
const l = 0
const r = 1
// 1 right 0 left
ln := cur.children[l]
lrn := ln.children[r]
tree.takeParent(cur, ln)
setChild(cur, l, lrn)
setChildNotNil(ln, r, cur)
cur.size = getChildrenSumSize(cur) + 1
ln.size = getChildrenSumSize(ln) + 1
return ln
}
func (tree *vbTree) lrotate3(cur *Node) *Node {
const l = 1
const r = 0
// 1 right 0 left
mov := cur.children[l]
cur.children[l] = nil
tree.takeParent(cur, mov)
setChildNotNil(mov, r, cur)
mov.size = 3
cur.size = 1
return mov
}
func (tree *vbTree) lrotate(cur *Node) *Node {
const l = 1
const r = 0
// 1 right 0 left
ln := cur.children[l]
lrn := ln.children[r]
tree.takeParent(cur, ln)
setChild(cur, l, lrn)
setChildNotNil(ln, r, cur)
cur.size = getChildrenSumSize(cur) + 1
ln.size = getChildrenSumSize(ln) + 1
return ln
}
func getChildrenSumSize(cur *Node) int {
return getSize(cur.children[0]) + getSize(cur.children[1])
}
func getChildrenSize(cur *Node) (int, int) {
return getSize(cur.children[0]), getSize(cur.children[1])
}
func getSize(cur *Node) int {
if cur == nil {
return 0
}
return cur.size
}
func (tree *vbTree) fixSizeWithRemove(cur *Node) {
for cur != nil {
cur.size--
if cur.size > 8 {
factor := cur.size / 10 // or factor = 1
ls, rs := getChildrenSize(cur)
if rs >= ls*2+factor || ls >= rs*2+factor {
cur = tree.fixSize(cur, ls, rs)
}
} else if cur.size == 3 {
if cur.children[0] == nil {
if cur.children[1].children[0] == nil {
cur = tree.lrotate3(cur)
} else {
cur = tree.lrrotate3(cur)
}
} else if cur.children[1] == nil {
if cur.children[0].children[1] == nil {
cur = tree.rrotate3(cur)
} else {
cur = tree.rlrotate3(cur)
}
}
}
cur = cur.parent
}
}
func (tree *vbTree) fixSize(cur *Node, ls, rs int) *Node {
if ls > rs {
llsize, lrsize := getChildrenSize(cur.children[0])
if lrsize > llsize {
return tree.rlrotate(cur)
}
return tree.rrotate(cur)
} else {
rlsize, rrsize := getChildrenSize(cur.children[1])
if rlsize > rrsize {
return tree.lrrotate(cur)
}
return tree.lrotate(cur)
}
}
func output(Node *Node, prefix string, isTail bool, str *string) {
if Node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
output(Node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
*str += spew.Sprint(Node.value) + "\n"
if Node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
output(Node.children[0], newPrefix, true, str)
}
}
func outputfordebug(Node *Node, prefix string, isTail bool, str *string) {
if Node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
outputfordebug(Node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
suffix := "("
parentv := ""
if Node.parent == nil {
parentv = "nil"
} else {
parentv = spew.Sprint(Node.parent.value)
}
suffix += parentv + "|" + spew.Sprint(Node.size) + ")"
*str += spew.Sprint(Node.value) + suffix + "\n"
if Node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
outputfordebug(Node.children[0], newPrefix, true, str)
}
}
func (tree *vbTree) debugString() string {
str := "AVLTree\n"
if tree.root == nil {
return str + "nil"
}
outputfordebug(tree.root, "", true, &str)
return str
}

656
priority_queue/vbt_test.go Normal file
View File

@@ -0,0 +1,656 @@
package pqueue
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"474420502.top/eson/structure/compare"
"github.com/huandu/skiplist"
"github.com/Pallinder/go-randomdata"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/avltree"
"github.com/emirpasic/gods/trees/redblacktree"
)
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 TestIndexRange(t *testing.T) {
tree := newVBT(compare.Int)
l := []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15}
for _, v := range l {
tree.Put(v)
}
// [3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50]
// t.Error(tree.Values(), tree.Size())
var result string
result = spew.Sprint(tree.IndexRange(0, 5))
if result != "[50 40 40 40 40 30] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(2, 5))
if result != "[40 40 40 30] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(10, 100))
if result != "[15 14 14 14 7 3] false" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(15, 0)) // size = 16, index max = 15
if result != "[3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(16, 0)) // size = 16, index max = 15
if result != "[3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50] false" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(5, 1)) // size = 16, index max = 15
if result != "[30 40 40 40 40] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(-1, -5)) // size = 16, index max = 15
if result != "[3 7 14 14 14] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(-1, -16)) // size = 16, index max = 0 - 15 (-1,-16)
if result != "[3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(-1, -17)) // size = 16, index max = 0 - 15 (-1,-16)
if result != "[3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50] false" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(-5, -1)) // size = 16, index max = 0 - 15 (-1,-16)
if result != "[14 14 14 7 3] true" {
t.Error(result)
}
}
func TestGetAround(t *testing.T) {
tree := newVBT(compare.Int)
for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
tree.Put(v)
}
var Result string
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(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(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 != "[17 <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> 7]" {
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
func TestPutStable(t *testing.T) {
// tree := newVBT(compare.Int)
// for i := 0; i < 40; i++ {
// v := randomdata.Number(0, 100)
// tree.Put(v)
// t.Error(tree.top, v)
// // t.Error(i, v)
// // t.Error(tree.debugString())
// }
// for i := 0; i < 40; i++ {
// v, _ := tree.Index(0)
// tree.RemoveIndex(0)
// t.Error(i, v)
// if tree.top != nil {
// t.Error(tree.top)
// }
// }
}
func TestPutComparatorRandom(t *testing.T) {
for n := 0; n < 30000; n++ {
tree := newVBT(compare.Int)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 50; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + ","
tree.Put(v)
godsavl.Put(v, v)
}
}
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(godsavl.Values())
if s1 != s2 {
t.Error(godsavl.String())
t.Error(tree.debugString())
t.Error(content, n)
break
}
}
}
func TestGet(t *testing.T) {
tree := newVBT(compare.Int)
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
tree.Put(v)
}
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
v, ok := tree.Get(v)
if !ok {
t.Error("the val not found ", v)
}
}
if v, ok := tree.Get(10000); ok {
t.Error("the val(1000) is not in tree, but is found", v)
}
}
func TestGetRange(t *testing.T) {
tree := newVBT(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v)
}
// t.Error(tree.debugString())
// t.Error(tree.getArountNode(20))
// t.Error(tree.Values())
result := tree.GetRange(0, 20)
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(-5, -1)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(7, 20)
if spew.Sprint(result) != "[8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(30, 40)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(30, 60)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(40, 40)
if spew.Sprint(result) != "[40]" {
t.Error(result)
}
result = tree.GetRange(50, 60)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(50, 1)
if spew.Sprint(result) != "[40 30 17 13 10 8 6 5 2 1]" {
t.Error(result)
}
result = tree.GetRange(30, 20)
if spew.Sprint(result) != "[30]" {
t.Error(result)
}
}
func TestTravalsal(t *testing.T) {
tree := newVBT(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v)
}
i := 0
var result []interface{}
tree.Traversal(func(v interface{}) bool {
result = append(result, v)
i++
if i >= 10 {
return false
}
return true
})
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17 30 40]" {
t.Error(result)
}
}
func TestRemoveAll(t *testing.T) {
ALL:
for c := 0; c < 20000; c++ {
tree := newVBT(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 50; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
l = append(l, v)
tree.Put(v)
gods.Put(v, v)
}
}
for i := 0; i < 50; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(gods.Values())
if s1 != s2 {
t.Error("avl remove error", "avlsize = ", tree.Size())
t.Error(tree.root, i, l[i])
t.Error(s1)
t.Error(s2)
break ALL
}
}
}
}
func TestRemove(t *testing.T) {
ALL:
for N := 0; N < 5000; N++ {
tree := newVBT(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 20; i++ {
v := randomdata.Number(0, 100)
if _, ok := m[v]; !ok {
l = append(l, v)
m[v] = v
tree.Put(v)
gods.Put(v, v)
}
}
src1 := tree.String()
src2 := gods.String()
for i := 0; i < 20; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
if tree.root != nil && spew.Sprint(gods.Values()) != spew.Sprint(tree.Values()) {
t.Error(src1)
t.Error(src2)
t.Error(tree.debugString())
t.Error(gods.String())
t.Error(l[i])
break 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) {
}
func BenchmarkIndexRange(b *testing.B) {
tree := newVBT(compare.Int)
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.IndexRange(i, i+49)
}
}
}
func BenchmarkSkipListSet(b *testing.B) {
l := loadTestData()
execCount := 1
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
sl := skiplist.New(skiplist.Int)
for _, v := range l {
sl.Set(v, v)
}
}
}
func BenchmarkIterator(b *testing.B) {
tree := newVBT(compare.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v)
}
b.ResetTimer()
b.StartTimer()
iter := tree.Iterator()
b.N = 0
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
for iter.Next() {
b.N++
}
b.Log(b.N, len(l))
}
func BenchmarkRemove(b *testing.B) {
tree := newVBT(compare.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < len(l); i++ {
tree.Remove(l[i])
}
}
func BenchmarkGodsRemove(b *testing.B) {
tree := avltree.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 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) {
tree := newVBT(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 5
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsRBGet(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], i)
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsAvlGet(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], i)
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkPut(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 50
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
tree := newVBT(compare.Int)
for _, v := range l {
tree.Put(v)
}
}
}
func BenchmarkIndex(b *testing.B) {
tree := newVBT(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i])
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
tree.Index(i)
}
}
func BenchmarkGodsRBPut(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}
func BenchmarkGodsPut(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}

View File

@@ -0,0 +1,230 @@
package pqueuekey
import (
"474420502.top/eson/structure/lastack"
)
type Iterator struct {
dir int
up *Node
cur *Node
tstack *lastack.Stack
// curnext *Node
}
func initIterator(avltree *vbTree) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = avltree.root
return iter
}
func NewIterator(n *Node) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = n
return iter
}
func NewIteratorWithCap(n *Node, cap int) *Iterator {
iter := &Iterator{tstack: lastack.NewWithCap(cap)}
iter.up = n
return iter
}
func (iter *Iterator) SeNode(n *Node) {
iter.up = n
iter.dir = 0
iter.tstack.Clear()
}
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) GetNext(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SeNode(cur)
iter.curPushNextStack(iter.up)
iter.up = iter.getNextUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getNextUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushNextStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Next() (result bool) {
if iter.dir > -1 {
if iter.dir == 1 && iter.cur != nil {
iter.tstack.Clear()
iter.curPushNextStack(iter.cur)
iter.up = iter.getNextUp(iter.cur)
}
iter.dir = -1
}
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
}
return false
}
func (iter *Iterator) GetPrev(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SeNode(cur)
iter.curPushPrevStack(iter.up)
iter.up = iter.getPrevUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushPrevStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Prev() (result bool) {
if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev)
if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈
iter.tstack.Clear()
iter.curPushPrevStack(iter.cur) // 把当前cur计算的逆向回朔
iter.up = iter.getPrevUp(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.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
iter.curPushPrevStack(iter.cur)
return true
}
// 如果再次计算的栈为空, 则只能返回false
return false
}
func getRelationship(cur *Node) int {
if cur.parent.children[1] == cur {
return 1
}
return 0
}
func (iter *Iterator) getPrevUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushPrevStack(cur *Node) {
Prev := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值
if Prev != nil {
iter.tstack.Push(Prev)
for Prev.children[1] != nil {
Prev = Prev.children[1]
iter.tstack.Push(Prev) // 入栈 用于回溯
}
}
}
func (iter *Iterator) getNextUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushNextStack(cur *Node) {
next := cur.children[1]
if next != nil {
iter.tstack.Push(next)
for next.children[0] != nil {
next = next.children[0]
iter.tstack.Push(next)
}
}
}

View File

@@ -0,0 +1,80 @@
package pqueuekey
import "474420502.top/eson/structure/compare"
type PriorityQueue struct {
queue *vbTree
}
func (pq *PriorityQueue) Iterator() *Iterator {
return NewIterator(pq.queue.top)
}
func New(Compare compare.Compare) *PriorityQueue {
return &PriorityQueue{queue: newVBT(Compare)}
}
func (pq *PriorityQueue) Size() int {
return pq.queue.Size()
}
func (pq *PriorityQueue) Push(key, value interface{}) {
pq.queue.Put(key, value)
}
func (pq *PriorityQueue) Top() (result interface{}, ok bool) {
if pq.queue.top != nil {
return pq.queue.top.value, true
}
return nil, false
}
func (pq *PriorityQueue) Pop() (result interface{}, ok bool) {
if pq.queue.top != nil {
result = pq.queue.top.value
pq.queue.removeNode(pq.queue.top)
return result, true
}
return nil, false
}
func (pq *PriorityQueue) Index(idx int) (interface{}, bool) {
return pq.queue.Index(idx)
}
func (pq *PriorityQueue) IndexNode(idx int) (*Node, bool) {
n := pq.queue.indexNode(idx)
return n, n != nil
}
func (pq *PriorityQueue) Get(key interface{}) (interface{}, bool) {
return pq.queue.Get(key)
}
func (pq *PriorityQueue) GetNode(key interface{}) (*Node, bool) {
return pq.queue.GetNode(key)
}
func (pq *PriorityQueue) GetAround(key interface{}) [3]interface{} {
return pq.queue.GetAround(key)
}
func (pq *PriorityQueue) GetAroundNode(key interface{}) [3]*Node {
return pq.queue.getArounNode(key)
}
func (pq *PriorityQueue) GetRange(k1, k2 interface{}) []interface{} {
return pq.queue.GetRange(k1, k2)
}
func (pq *PriorityQueue) RemoveIndex(idx int) (interface{}, bool) {
return pq.queue.RemoveIndex(idx)
}
func (pq *PriorityQueue) Remove(key interface{}) (interface{}, bool) {
return pq.queue.Remove(key)
}
func (pq *PriorityQueue) Values() []interface{} {
return pq.queue.Values()
}

View File

@@ -0,0 +1,347 @@
package pqueuekey
import (
"testing"
"github.com/davecgh/go-spew/spew"
"474420502.top/eson/structure/compare"
)
func TestQueuePush(t *testing.T) {
pq := New(compare.Int)
for _, v := range []int{32, 10, 53, 78, 90, 1, 4} {
pq.Push(v, v)
if v, ok := pq.Top(); ok {
} else {
t.Error(v)
}
}
if v, ok := pq.Top(); ok {
if v != 90 {
t.Error(v)
}
} else {
t.Error(v)
}
}
func TestQueuePop(t *testing.T) {
pq := New(compare.Int)
for _, v := range []int{32, 10, 53, 78, 90, 1, 4} {
pq.Push(v, v)
if v, ok := pq.Top(); ok {
} else {
t.Error(v)
}
}
l := []int{90, 78, 53, 32, 10, 4, 1}
for _, lv := range l {
if v, ok := pq.Pop(); ok {
if v != lv {
t.Error(v)
}
} else {
t.Error(v)
}
}
if v, ok := pq.Pop(); ok {
t.Error(v)
}
}
func TestQueueGet(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v, v)
}
if v, ok := pq.Get(0); ok {
t.Error(v)
}
if v, ok := pq.Get(70); ok {
t.Error(v)
}
for _, v := range l {
if gv, ok := pq.Get(v); ok {
if gv != v {
t.Error("Get value is error, value is", gv)
}
}
}
}
func TestQueueGetRange(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v, v)
}
var result string
result = spew.Sprint(pq.GetRange(10, 40))
if result != "[10 32]" {
t.Error(result)
}
result = spew.Sprint(pq.GetRange(1, 90))
if result != "[1 4 10 32 53 78 90]" {
t.Error(result)
}
result = spew.Sprint(pq.GetRange(0, 90))
if result != "[1 4 10 32 53 78 90]" {
t.Error(result)
}
result = spew.Sprint(pq.GetRange(1, 100))
if result != "[1 4 10 32 53 78 90]" {
t.Error(result)
}
result = spew.Sprint(pq.GetRange(5, 88))
if result != "[10 32 53 78]" {
t.Error(result)
}
}
func TestQueueGetAround(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v, v)
}
var result string
result = spew.Sprint(pq.GetAround(53))
if result != "[32 53 78]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(52))
if result != "[32 <nil> 53]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(1))
if result != "[<nil> 1 4]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(90))
if result != "[78 90 <nil>]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(0))
if result != "[<nil> <nil> 1]" {
t.Error(result)
}
result = spew.Sprint(pq.GetAround(100))
if result != "[90 <nil> <nil>]" {
t.Error(result)
}
}
func TestQueueRemove(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v, v)
}
content := ""
for _, v := range l {
pq.Remove(v)
content += spew.Sprint(pq.Values())
}
if content != "[1 4 10 53 78 90][1 4 53 78 90][1 4 78 90][1 4 90][1 4][4][]" {
t.Error(content)
}
}
func TestQueueRemoveIndex(t *testing.T) {
pq := New(compare.Int)
l := []int{32, 10, 53, 78, 90, 1, 4}
for _, v := range l {
pq.Push(v, v)
}
content := ""
for range l {
pq.RemoveIndex(0)
content += spew.Sprint(pq.Values())
}
if content != "[1 4 10 32 53 78][1 4 10 32 53][1 4 10 32][1 4 10][1 4][1][]" {
t.Error(content)
}
if n, ok := pq.RemoveIndex(0); ok {
t.Error("pq is not exist elements", n)
}
}
func TestQueueIndex(t *testing.T) {
pq := New(compare.Int)
for _, v := range []int{32, 10, 53, 78, 90, 1, 4} {
pq.Push(v, v)
}
l := []int{90, 78, 53, 32, 10, 4, 1}
for i, lv := range l {
if v, ok := pq.Index(len(l) - i - 1); ok {
if v != l[len(l)-i-1] {
t.Error(v)
}
} else {
t.Error(i, "index is not exist")
}
if v, ok := pq.Index(i); ok {
if v != lv {
t.Error(v)
}
} else {
t.Error(i, "index is not exist")
}
}
if v, ok := pq.Index(-1); ok {
if v != 1 {
t.Error(v)
}
} else {
t.Error("-1 index is not exist")
}
if v, ok := pq.Index(pq.Size()); ok {
t.Error("index is exits", pq.Size(), v)
}
if v, ok := pq.Index(pq.Size() - 1); !ok {
if v != 1 {
t.Error("the last value is 1 not is ", v)
}
}
if v, ok := pq.Index(-10); ok {
t.Error("-10 index is exits", v)
}
}
func BenchmarkQueueGet(b *testing.B) {
l := loadTestData()
pq := New(compare.Int)
for _, v := range l {
pq.Push(v, v)
}
execCount := 5
b.N = len(l) * execCount
b.ResetTimer()
b.StartTimer()
ALL:
for i := 0; i < execCount; i++ {
for _, v := range l {
if gv, ok := pq.Get(v); !ok {
b.Error(gv)
break ALL
}
}
}
}
func BenchmarkQueueRemove(b *testing.B) {
l := loadTestData()
pq := New(compare.Int)
for _, v := range l {
pq.Push(v, v)
}
b.N = len(l)
b.ResetTimer()
b.StartTimer()
for _, v := range l {
pq.Remove(v)
}
}
func BenchmarkQueueIndex(b *testing.B) {
l := loadTestData()
pq := New(compare.Int)
for _, v := range l {
pq.Push(v, v)
}
execCount := 2
b.N = len(l) * execCount
b.ResetTimer()
b.StartTimer()
ALL:
for i := 0; i < execCount; i++ {
for idx := range l {
if v, ok := pq.Index(idx); !ok {
b.Error(v)
break ALL
}
}
}
}
func BenchmarkPriorityPush(b *testing.B) {
l := loadTestData()
execCount := 5
b.N = len(l) * execCount
b.ResetTimer()
b.StartTimer()
for i := 0; i < execCount; i++ {
pq := New(compare.Int)
for _, v := range l {
pq.Push(v, v)
}
}
}
func BenchmarkPriorityPop(b *testing.B) {
l := loadTestData()
pq := New(compare.Int)
for _, v := range l {
pq.Push(v, v)
}
b.N = len(l)
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
pq.Pop()
}
}

982
priority_queuekey/vbt.go Normal file
View File

@@ -0,0 +1,982 @@
package pqueuekey
import (
"474420502.top/eson/structure/compare"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
children [2]*Node
parent *Node
size int
key, value interface{}
}
func (n *Node) String() string {
if n == nil {
return "nil"
}
p := "nil"
if n.parent != nil {
p = spew.Sprint(n.parent.value)
}
return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.size) + ")"
}
type vbTree struct {
root *Node
Compare compare.Compare
top *Node
iter *Iterator
}
func newVBT(Compare compare.Compare) *vbTree {
return &vbTree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)}
}
func (tree *vbTree) String() string {
str := "AVLTree\n"
if tree.root == nil {
return str + "nil"
}
output(tree.root, "", true, &str)
return str
}
func (tree *vbTree) Iterator() *Iterator {
return initIterator(tree)
}
func (tree *vbTree) Size() int {
if tree.root == nil {
return 0
}
return tree.root.size
}
func (tree *vbTree) indexNode(idx int) *Node {
cur := tree.root
if idx >= 0 {
for cur != nil {
rs := getSize(cur.children[1])
if idx == rs {
return cur
} else if idx < rs {
cur = cur.children[1]
} else {
idx = idx - rs - 1
cur = cur.children[0]
}
}
} else {
idx = -idx - 1
for cur != nil {
ls := getSize(cur.children[0])
if idx == ls {
return cur
} else if idx < ls {
cur = cur.children[0]
} else {
idx = idx - ls - 1
cur = cur.children[1]
}
}
}
return nil
}
func (tree *vbTree) Index(idx int) (interface{}, bool) {
n := tree.indexNode(idx)
if n != nil {
return n.value, true
}
return nil, false
}
func (tree *vbTree) IndexRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1
if idx1^idx2 < 0 {
if idx1 < 0 {
idx1 = tree.root.size + idx1 - 1
} else {
idx2 = tree.root.size + idx2 - 1
}
}
if idx1 > idx2 {
ok = true
if idx1 >= tree.root.size {
idx1 = tree.root.size - 1
ok = false
}
n := tree.indexNode(idx1)
tree.iter.SeNode(n)
iter := tree.iter
result = make([]interface{}, 0, idx1-idx2)
for i := idx2; i <= idx1; i++ {
if iter.Next() {
result = append(result, iter.Value())
} else {
ok = false
return
}
}
return
} else {
ok = true
if idx2 >= tree.root.size {
idx2 = tree.root.size - 1
ok = false
}
if n := tree.indexNode(idx1); n != nil {
tree.iter.SeNode(n)
iter := tree.iter
result = make([]interface{}, 0, idx2-idx1)
for i := idx1; i <= idx2; i++ {
if iter.Prev() {
result = append(result, iter.Value())
} else {
ok = false
return
}
}
return
}
}
return nil, false
}
func (tree *vbTree) RemoveIndex(idx int) (interface{}, bool) {
n := tree.indexNode(idx)
if n != nil {
tree.removeNode(n)
return n.value, true
}
return nil, false
}
func (tree *vbTree) removeNode(n *Node) {
if tree.root.size == 1 {
tree.root = nil
tree.top = nil
// return n
return
}
if tree.top == n {
tree.top = tree.iter.GetPrev(n, 1)
}
ls, rs := getChildrenSize(n)
if ls == 0 && rs == 0 {
p := n.parent
p.children[getRelationship(n)] = nil
tree.fixSizeWithRemove(p)
// return n
return
}
var cur *Node
if ls > rs {
cur = n.children[0]
for cur.children[1] != nil {
cur = cur.children[1]
}
cleft := cur.children[0]
cur.parent.children[getRelationship(cur)] = cleft
if cleft != nil {
cleft.parent = cur.parent
}
} else {
cur = n.children[1]
for cur.children[0] != nil {
cur = cur.children[0]
}
cright := cur.children[1]
cur.parent.children[getRelationship(cur)] = cright
if cright != nil {
cright.parent = cur.parent
}
}
cparent := cur.parent
// 修改为interface 交换
// n.value, cur.value = cur.value, n.value
tree.replace(n, cur)
// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
if cparent == n {
tree.fixSizeWithRemove(cur)
} else {
tree.fixSizeWithRemove(cparent)
}
// return cur
return
}
func (tree *vbTree) Remove(key interface{}) (interface{}, bool) {
if n, ok := tree.GetNode(key); ok {
tree.removeNode(n)
return n.value, true
}
// return nil
return nil, false
}
// Values 返回先序遍历的值
func (tree *vbTree) Values() []interface{} {
mszie := 0
if tree.root != nil {
mszie = tree.root.size
}
result := make([]interface{}, 0, mszie)
tree.Traversal(func(k, v interface{}) bool {
result = append(result, v)
return true
}, LDR)
return result
}
func (tree *vbTree) GetRange(k1, k2 interface{}) (result []interface{}) {
c := tree.Compare(k2, k1)
switch c {
case 1:
var min, max *Node
resultmin := tree.getArounNode(k1)
resultmax := tree.getArounNode(k2)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if max == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
// iter := NewIterator(min)
tree.iter.SeNode(min)
iter := tree.iter
for iter.Next() {
result = append(result, iter.Value())
if iter.cur == max {
break
}
}
case -1:
var min, max *Node
resultmin := tree.getArounNode(k2)
resultmax := tree.getArounNode(k1)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if min == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
// iter := NewIterator(max)
tree.iter.SeNode(max)
iter := tree.iter
for iter.Prev() {
result = append(result, iter.Value())
if iter.cur == min {
break
}
}
case 0:
if n, ok := tree.GetNode(k1); ok {
return []interface{}{n.value}
}
return []interface{}{}
}
return
}
func (tree *vbTree) Get(key interface{}) (interface{}, bool) {
n, ok := tree.GetNode(key)
if ok {
return n.value, true
}
return n, false
}
func (tree *vbTree) GetAround(key interface{}) (result [3]interface{}) {
an := tree.getArounNode(key)
for i, n := range an {
if n != nil {
result[i] = n.value
}
}
return
}
func (tree *vbTree) getArounNode(key interface{}) (result [3]*Node) {
var last *Node
var lastc int
for n := tree.root; n != nil; {
last = n
c := tree.Compare(key, n.key)
switch c {
case -1:
n = n.children[0]
lastc = c
case 1:
n = n.children[1]
lastc = c
case 0:
tree.iter.SeNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.key, n.key) == 0 {
n = iter.cur
} else {
break
}
}
result[1] = n
n = nil
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
switch lastc {
case 1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[0] = last
result[2] = tree.iter.GetNext(last, 1)
}
case -1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[2] = last
result[0] = tree.iter.GetPrev(last, 1)
}
case 0:
if result[1] == nil {
return
}
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
}
return
}
func (tree *vbTree) GetNode(key interface{}) (*Node, bool) {
for n := tree.root; n != nil; {
switch c := tree.Compare(key, n.key); c {
case -1:
n = n.children[0]
case 1:
n = n.children[1]
case 0:
tree.iter.SeNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.key, n.key) == 0 {
n = iter.cur
} else {
break
}
}
return n, true
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
return nil, false
}
func (tree *vbTree) Put(key, value interface{}) {
Node := &Node{key: key, value: value, size: 1}
if tree.root == nil {
tree.root = Node
tree.top = Node
return
}
if tree.Compare(key, tree.top.key) > 0 {
tree.top = Node
}
for cur := tree.root; ; {
if cur.size > 8 {
factor := cur.size / 10 // or factor = 1
ls, rs := cur.children[0].size, cur.children[1].size
if rs >= ls*2+factor || ls >= rs*2+factor {
cur = tree.fixSize(cur, ls, rs)
}
}
cur.size++
c := tree.Compare(key, cur.key)
if c < 0 {
if cur.children[0] == nil {
cur.children[0] = Node
Node.parent = cur
if cur.parent != nil && cur.parent.size == 3 {
if cur.parent.children[0] == nil {
tree.lrrotate3(cur.parent)
} else {
tree.rrotate3(cur.parent)
}
}
return
}
cur = cur.children[0]
} else {
if cur.children[1] == nil {
cur.children[1] = Node
Node.parent = cur
if cur.parent != nil && cur.parent.size == 3 {
if cur.parent.children[1] == nil {
tree.rlrotate3(cur.parent)
} else {
tree.lrotate3(cur.parent)
}
}
return
}
cur = cur.children[1]
}
}
}
type TraversalMethod int
const (
// L = left R = right D = Value(dest)
_ TraversalMethod = iota
//DLR 先值 然后左递归 右递归 下面同理
DLR
//LDR 先从左边有序访问到右边 从小到大
LDR
// LRD 同理
LRD
// DRL 同理
DRL
// RDL 先从右边有序访问到左边 从大到小
RDL
// RLD 同理
RLD
)
// Traversal 遍历的方法 默认是LDR 从小到大 Compare 为 l < r
func (tree *vbTree) Traversal(every func(k, v interface{}) bool, traversalMethod ...interface{}) {
if tree.root == nil {
return
}
method := LDR
if len(traversalMethod) != 0 {
method = traversalMethod[0].(TraversalMethod)
}
switch method {
case DLR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LDR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LRD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
return true
}
traverasl(tree.root)
case DRL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case RDL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
return true
}
traverasl(tree.root)
case RLD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
return true
}
traverasl(tree.root)
}
}
func setChildNotNil(cur *Node, cidx int, child *Node) {
cur.children[cidx] = child
cur.children[cidx].parent = cur
}
func setChild(cur *Node, cidx int, child *Node) {
cur.children[cidx] = child
if child != nil {
cur.children[cidx].parent = cur
}
}
func (tree *vbTree) replace(old, new *Node) {
setChild(new, 0, old.children[0])
setChild(new, 1, old.children[1])
if old.parent == nil {
tree.root = new
} else {
if old.parent.children[1] == old {
old.parent.children[1] = new
} else {
old.parent.children[0] = new
}
}
new.size = old.size
new.parent = old.parent
}
func (tree *vbTree) takeParent(token, person *Node) {
if token.parent == nil {
tree.root = person
} else {
if token.parent.children[1] == token {
token.parent.children[1] = person
} else {
token.parent.children[0] = person
}
}
person.parent = token.parent
}
func (tree *vbTree) lrrotate3(cur *Node) *Node {
const l = 1
const r = 0
ln := cur.children[l]
cur.children[l] = nil
lrn := ln.children[r]
ln.children[r] = nil
tree.takeParent(cur, lrn)
setChildNotNil(lrn, l, ln)
setChildNotNil(lrn, r, cur)
lrn.size = 3
lrn.children[l].size = 1
lrn.children[r].size = 1
return lrn
}
func (tree *vbTree) lrrotate(cur *Node) *Node {
const l = 1
const r = 0
ln := cur.children[l]
lrn := ln.children[r]
lrln := lrn.children[l]
lrrn := lrn.children[r]
tree.takeParent(cur, lrn)
setChild(ln, r, lrln)
setChild(cur, l, lrrn)
setChildNotNil(lrn, l, ln)
setChildNotNil(lrn, r, cur)
ln.size = getChildrenSumSize(ln) + 1
cur.size = getChildrenSumSize(cur) + 1
lrn.size = getChildrenSumSize(lrn) + 1
return lrn
}
func (tree *vbTree) rlrotate3(cur *Node) *Node {
const l = 0
const r = 1
ln := cur.children[l]
cur.children[l] = nil
lrn := ln.children[r]
ln.children[r] = nil
tree.takeParent(cur, lrn)
setChildNotNil(lrn, l, ln)
setChildNotNil(lrn, r, cur)
lrn.size = 3
lrn.children[l].size = 1
lrn.children[r].size = 1
return lrn
}
func (tree *vbTree) rlrotate(cur *Node) *Node {
const l = 0
const r = 1
ln := cur.children[l]
lrn := ln.children[r]
lrln := lrn.children[l]
lrrn := lrn.children[r]
tree.takeParent(cur, lrn)
setChild(ln, r, lrln)
setChild(cur, l, lrrn)
setChildNotNil(lrn, l, ln)
setChildNotNil(lrn, r, cur)
ln.size = getChildrenSumSize(ln) + 1
cur.size = getChildrenSumSize(cur) + 1
lrn.size = getChildrenSumSize(lrn) + 1
return lrn
}
func (tree *vbTree) rrotate3(cur *Node) *Node {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
cur.children[l] = nil
tree.takeParent(cur, mov)
setChildNotNil(mov, r, cur)
mov.size = 3
cur.size = 1
return mov
}
func (tree *vbTree) rrotate(cur *Node) *Node {
const l = 0
const r = 1
// 1 right 0 left
ln := cur.children[l]
lrn := ln.children[r]
tree.takeParent(cur, ln)
setChild(cur, l, lrn)
setChildNotNil(ln, r, cur)
cur.size = getChildrenSumSize(cur) + 1
ln.size = getChildrenSumSize(ln) + 1
return ln
}
func (tree *vbTree) lrotate3(cur *Node) *Node {
const l = 1
const r = 0
// 1 right 0 left
mov := cur.children[l]
cur.children[l] = nil
tree.takeParent(cur, mov)
setChildNotNil(mov, r, cur)
mov.size = 3
cur.size = 1
return mov
}
func (tree *vbTree) lrotate(cur *Node) *Node {
const l = 1
const r = 0
// 1 right 0 left
ln := cur.children[l]
lrn := ln.children[r]
tree.takeParent(cur, ln)
setChild(cur, l, lrn)
setChildNotNil(ln, r, cur)
cur.size = getChildrenSumSize(cur) + 1
ln.size = getChildrenSumSize(ln) + 1
return ln
}
func getChildrenSumSize(cur *Node) int {
return getSize(cur.children[0]) + getSize(cur.children[1])
}
func getChildrenSize(cur *Node) (int, int) {
return getSize(cur.children[0]), getSize(cur.children[1])
}
func getSize(cur *Node) int {
if cur == nil {
return 0
}
return cur.size
}
func (tree *vbTree) fixSizeWithRemove(cur *Node) {
for cur != nil {
cur.size--
if cur.size > 8 {
factor := cur.size / 10 // or factor = 1
ls, rs := getChildrenSize(cur)
if rs >= ls*2+factor || ls >= rs*2+factor {
cur = tree.fixSize(cur, ls, rs)
}
} else if cur.size == 3 {
if cur.children[0] == nil {
if cur.children[1].children[0] == nil {
cur = tree.lrotate3(cur)
} else {
cur = tree.lrrotate3(cur)
}
} else if cur.children[1] == nil {
if cur.children[0].children[1] == nil {
cur = tree.rrotate3(cur)
} else {
cur = tree.rlrotate3(cur)
}
}
}
cur = cur.parent
}
}
func (tree *vbTree) fixSize(cur *Node, ls, rs int) *Node {
if ls > rs {
llsize, lrsize := getChildrenSize(cur.children[0])
if lrsize > llsize {
return tree.rlrotate(cur)
}
return tree.rrotate(cur)
} else {
rlsize, rrsize := getChildrenSize(cur.children[1])
if rlsize > rrsize {
return tree.lrrotate(cur)
}
return tree.lrotate(cur)
}
}
func output(Node *Node, prefix string, isTail bool, str *string) {
if Node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
output(Node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
*str += spew.Sprint(Node.value) + "\n"
if Node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
output(Node.children[0], newPrefix, true, str)
}
}
func outputfordebug(Node *Node, prefix string, isTail bool, str *string) {
if Node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
outputfordebug(Node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
suffix := "("
parentv := ""
if Node.parent == nil {
parentv = "nil"
} else {
parentv = spew.Sprint(Node.parent.value)
}
suffix += parentv + "|" + spew.Sprint(Node.size) + ")"
*str += spew.Sprint(Node.value) + suffix + "\n"
if Node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
outputfordebug(Node.children[0], newPrefix, true, str)
}
}
func (tree *vbTree) debugString() string {
str := "AVLTree\n"
if tree.root == nil {
return str + "nil"
}
outputfordebug(tree.root, "", true, &str)
return str
}

View File

@@ -0,0 +1,656 @@
package pqueuekey
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"474420502.top/eson/structure/compare"
"github.com/huandu/skiplist"
"github.com/Pallinder/go-randomdata"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/avltree"
"github.com/emirpasic/gods/trees/redblacktree"
)
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 TestIndexRange(t *testing.T) {
tree := newVBT(compare.Int)
l := []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15}
for _, v := range l {
tree.Put(v, v)
}
// [3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50]
// t.Error(tree.Values(), tree.Size())
var result string
result = spew.Sprint(tree.IndexRange(0, 5))
if result != "[50 40 40 40 40 30] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(2, 5))
if result != "[40 40 40 30] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(10, 100))
if result != "[15 14 14 14 7 3] false" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(15, 0)) // size = 16, index max = 15
if result != "[3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(16, 0)) // size = 16, index max = 15
if result != "[3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50] false" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(5, 1)) // size = 16, index max = 15
if result != "[30 40 40 40 40] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(-1, -5)) // size = 16, index max = 15
if result != "[3 7 14 14 14] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(-1, -16)) // size = 16, index max = 0 - 15 (-1,-16)
if result != "[3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(-1, -17)) // size = 16, index max = 0 - 15 (-1,-16)
if result != "[3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50] false" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(-5, -1)) // size = 16, index max = 0 - 15 (-1,-16)
if result != "[14 14 14 7 3] true" {
t.Error(result)
}
}
func TestGetAround(t *testing.T) {
tree := newVBT(compare.Int)
for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
tree.Put(v, v)
}
var Result string
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(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(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 != "[17 <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> 7]" {
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
func TestPutStable(t *testing.T) {
// tree := newVBT(compare.Int)
// for i := 0; i < 40; i++ {
// v := randomdata.Number(0, 100)
// tree.Put(v,v)
// t.Error(tree.top, v)
// // t.Error(i, v)
// // t.Error(tree.debugString())
// }
// for i := 0; i < 40; i++ {
// v, _ := tree.Index(0)
// tree.RemoveIndex(0)
// t.Error(i, v)
// if tree.top != nil {
// t.Error(tree.top)
// }
// }
}
func TestPutComparatorRandom(t *testing.T) {
for n := 0; n < 30000; n++ {
tree := newVBT(compare.Int)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 50; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + ","
tree.Put(v, v)
godsavl.Put(v, v)
}
}
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(godsavl.Values())
if s1 != s2 {
t.Error(godsavl.String())
t.Error(tree.debugString())
t.Error(content, n)
break
}
}
}
func TestGet(t *testing.T) {
tree := newVBT(compare.Int)
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
tree.Put(v, v)
}
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
v, ok := tree.Get(v)
if !ok {
t.Error("the val not found ", v)
}
}
if v, ok := tree.Get(10000); ok {
t.Error("the val(1000) is not in tree, but is found", v)
}
}
func TestGetRange(t *testing.T) {
tree := newVBT(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v, v)
}
// t.Error(tree.debugString())
// t.Error(tree.getArountNode(20))
// t.Error(tree.Values())
result := tree.GetRange(0, 20)
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(-5, -1)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(7, 20)
if spew.Sprint(result) != "[8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(30, 40)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(30, 60)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(40, 40)
if spew.Sprint(result) != "[40]" {
t.Error(result)
}
result = tree.GetRange(50, 60)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(50, 1)
if spew.Sprint(result) != "[40 30 17 13 10 8 6 5 2 1]" {
t.Error(result)
}
result = tree.GetRange(30, 20)
if spew.Sprint(result) != "[30]" {
t.Error(result)
}
}
func TestTravalsal(t *testing.T) {
tree := newVBT(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v, v)
}
i := 0
var result []interface{}
tree.Traversal(func(k, v interface{}) bool {
result = append(result, v)
i++
if i >= 10 {
return false
}
return true
})
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17 30 40]" {
t.Error(result)
}
}
func TestRemoveAll(t *testing.T) {
ALL:
for c := 0; c < 20000; c++ {
tree := newVBT(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 50; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
l = append(l, v)
tree.Put(v, v)
gods.Put(v, v)
}
}
for i := 0; i < 50; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(gods.Values())
if s1 != s2 {
t.Error("avl remove error", "avlsize = ", tree.Size())
t.Error(tree.root, i, l[i])
t.Error(s1)
t.Error(s2)
break ALL
}
}
}
}
func TestRemove(t *testing.T) {
ALL:
for N := 0; N < 5000; N++ {
tree := newVBT(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 20; i++ {
v := randomdata.Number(0, 100)
if _, ok := m[v]; !ok {
l = append(l, v)
m[v] = v
tree.Put(v, v)
gods.Put(v, v)
}
}
src1 := tree.String()
src2 := gods.String()
for i := 0; i < 20; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
if tree.root != nil && spew.Sprint(gods.Values()) != spew.Sprint(tree.Values()) {
t.Error(src1)
t.Error(src2)
t.Error(tree.debugString())
t.Error(gods.String())
t.Error(l[i])
break 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) {
}
func BenchmarkIndexRange(b *testing.B) {
tree := newVBT(compare.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
b.ResetTimer()
b.StartTimer()
execCount := 5
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for range l {
tree.IndexRange(i, i+49)
}
}
}
func BenchmarkSkipListSet(b *testing.B) {
l := loadTestData()
execCount := 1
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
sl := skiplist.New(skiplist.Int)
for _, v := range l {
sl.Set(v, v)
}
}
}
func BenchmarkIterator(b *testing.B) {
tree := newVBT(compare.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
b.ResetTimer()
b.StartTimer()
iter := tree.Iterator()
b.N = 0
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
for iter.Next() {
b.N++
}
b.Log(b.N, len(l))
}
func BenchmarkRemove(b *testing.B) {
tree := newVBT(compare.Int)
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 BenchmarkGodsRemove(b *testing.B) {
tree := avltree.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 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) {
tree := newVBT(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 5
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsRBGet(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], i)
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsAvlGet(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], i)
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkPut(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 50
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
tree := newVBT(compare.Int)
for _, v := range l {
tree.Put(v, v)
}
}
}
func BenchmarkIndex(b *testing.B) {
tree := newVBT(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], l[i])
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
tree.Index(i)
}
}
func BenchmarkGodsRBPut(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}
func BenchmarkGodsPut(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}

80
set/hashset/hashset.go Normal file
View File

@@ -0,0 +1,80 @@
package hashset
import (
"fmt"
"strings"
)
var nullItem = struct{}{}
// HashSet
type HashSet struct {
hm map[interface{}]struct{}
}
// New
func New() *HashSet {
return &HashSet{hm: make(map[interface{}]struct{})}
}
// Add
func (set *HashSet) Add(items ...interface{}) {
for _, item := range items {
if _, ok := set.hm[item]; !ok {
set.hm[item] = nullItem
}
}
}
// Remove
func (set *HashSet) Remove(items ...interface{}) {
for _, item := range items {
delete(set.hm, item)
}
}
// Values
func (set *HashSet) Values() []interface{} {
values := make([]interface{}, set.Size())
count := 0
for item := range set.hm {
values[count] = item
count++
}
return values
}
// Contains
func (set *HashSet) Contains(item interface{}) bool {
if _, contains := set.hm[item]; contains {
return true
}
return false
}
// Empty
func (set *HashSet) Empty() bool {
return set.Size() == 0
}
// Clear
func (set *HashSet) Clear() {
set.hm = make(map[interface{}]struct{})
}
// Size
func (set *HashSet) Size() int {
return len(set.hm)
}
// String
func (set *HashSet) String() string {
content := "["
items := []string{}
for k := range set.hm {
items = append(items, fmt.Sprintf("%v", k))
}
content += strings.Join(items, ",")
content += "]"
return content
}

View File

@@ -0,0 +1,54 @@
package hashset
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
)
func loadTestData() []int {
log.SetFlags(log.Lshortfile)
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 TestAdd(t *testing.T) {
set := New()
for i := 0; i < 10; i++ {
set.Add(i)
}
if set.Size() != 10 {
t.Error("size is not equals to 10")
}
}
func TestRemove(t *testing.T) {
set := New()
for i := 0; i < 10; i++ {
set.Add(i)
}
for i := 0; i < 9; i++ {
set.Remove(i)
}
if set.Size() != 1 {
t.Error("size is not equals to 0")
}
if set.Values()[0] != 9 {
t.Error("remain is not 9")
}
}

85
set/treeset/treeset.go Normal file
View File

@@ -0,0 +1,85 @@
package treeset
import (
"fmt"
"strings"
"474420502.top/eson/structure/avldup"
"474420502.top/eson/structure/compare"
)
// TreeSet
type TreeSet struct {
tree *avldup.Tree
}
// New
func New(Compare compare.Compare) *TreeSet {
return &TreeSet{tree: avldup.New(Compare)}
}
// Add
func (set *TreeSet) Add(items ...interface{}) {
for _, item := range items {
set.tree.Put(item)
}
}
// Remove
func (set *TreeSet) Remove(items ...interface{}) {
for _, item := range items {
set.tree.Remove(item)
}
}
// Values
func (set *TreeSet) Values() []interface{} {
return set.tree.Values()
}
// Contains
func (set *TreeSet) Contains(item interface{}) bool {
if _, ok := set.tree.Get(item); ok {
return true
}
return false
}
// Contains the result is [r1,r2], not [r1, r2)
func (set *TreeSet) GetRange(r1, r2 interface{}) (result []interface{}) {
return set.tree.GetRange(r1, r2)
}
// Contains the result is [r1,item,r2] r1->item->r2 are close-knit
func (set *TreeSet) GetAround(item interface{}) (result [3]interface{}) {
return set.tree.GetAround(item)
}
// Empty
func (set *TreeSet) Empty() bool {
return set.Size() == 0
}
// Clear
func (set *TreeSet) Clear() {
set.tree.Clear()
}
// Size
func (set *TreeSet) Size() int {
return set.tree.Size()
}
// String
func (set *TreeSet) String() string {
content := "HashSet\n"
items := []string{}
set.tree.Traversal(func(k interface{}) bool {
items = append(items, fmt.Sprintf("%v", k))
return true
})
content += strings.Join(items, ", ")
return content
}

View File

@@ -0,0 +1 @@
package treeset

View File

@@ -0,0 +1,153 @@
package array2
type Array2 struct {
sizes []int
ysize int
xsize int
data [][]interface{}
cap int
}
func New() *Array2 {
return NewWithCap(8, 8)
}
func NewWithCap(ysize, xsize int) *Array2 {
arr := &Array2{ysize: ysize, xsize: xsize}
arr.sizes = make([]int, arr.ysize, arr.ysize)
arr.data = make([][]interface{}, arr.ysize, arr.ysize)
arr.cap = arr.ysize * arr.xsize
return arr
}
func (arr *Array2) debugValues() []interface{} {
var result []interface{}
for _, y := range arr.data {
if y != nil {
for _, v := range y {
if v == nil {
result = append(result, struct{}{})
} else {
result = append(result, v)
}
}
} else {
for i := 0; i < arr.xsize; i++ {
result = append(result, nil)
}
}
}
return result
}
func (arr *Array2) Values() []interface{} {
var result []interface{}
for _, y := range arr.data {
if y != nil {
for _, v := range y {
if v == nil {
result = append(result, nil)
} else {
result = append(result, v)
}
}
} else {
for i := 0; i < arr.xsize; i++ {
result = append(result, nil)
}
}
}
return result
}
func (arr *Array2) Cap() int {
return arr.cap
}
func (arr *Array2) Grow(size int) {
arr.ysize += size
temp := make([][]interface{}, arr.ysize, arr.ysize)
copy(temp, arr.data)
arr.data = temp
tempsizes := make([]int, arr.ysize, arr.ysize)
copy(tempsizes, arr.sizes)
arr.sizes = tempsizes
arr.cap = arr.ysize * arr.xsize
}
func (arr *Array2) Set(idx int, value interface{}) {
yindex := idx / arr.xsize
xindex := idx % arr.xsize
xdata := arr.data[yindex]
if xdata == nil {
xdata = make([]interface{}, arr.xsize, arr.xsize)
arr.data[yindex] = xdata
}
if xdata[xindex] == nil {
arr.sizes[yindex]++
}
xdata[xindex] = value
}
func (arr *Array2) Get(idx int) (interface{}, bool) {
yindex := idx / arr.xsize
xindex := idx % arr.xsize
xdata := arr.data[yindex]
if xdata == nil {
return nil, false
}
v := xdata[xindex]
return v, v != nil
}
func (arr *Array2) GetOrSet(idx int, DoSetValue func([]interface{}, int)) (result interface{}, isSet bool) {
yindex := idx / arr.xsize
xindex := idx % arr.xsize
xdata := arr.data[yindex]
if xdata == nil {
xdata = make([]interface{}, arr.xsize, arr.xsize)
arr.data[yindex] = xdata
}
result = xdata[xindex]
if result == nil {
DoSetValue(xdata, xindex)
result = xdata[xindex]
if result == nil {
panic("DoSetValue Not Set <nil> Value")
}
arr.sizes[yindex]++
return result, true
}
return result, false
}
func (arr *Array2) Del(idx int) (interface{}, bool) {
yindex := idx / arr.xsize
xindex := idx % arr.xsize
xdata := arr.data[yindex]
if xdata == nil {
return nil, false
}
v := xdata[xindex]
xdata[xindex] = nil
isnil := v != nil
if isnil {
arr.sizes[yindex]--
if arr.sizes[yindex] == 0 {
arr.data[yindex] = nil
}
}
return v, isnil
}

View File

@@ -0,0 +1,248 @@
package array2
import (
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/Pallinder/go-randomdata"
)
func testSet1(t *testing.T) {
arr := NewWithCap(4, 4)
l := []int{0, 6, 5, 15}
for _, v := range l {
arr.Set(v, v)
}
var result string
result = spew.Sprint(arr.debugValues())
if result != "[0 {} {} {} {} 5 6 {} <nil> <nil> <nil> <nil> {} {} {} 15]" {
t.Error(result)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the set is out of range")
}
}()
arr.Set(16, 16)
}
func testSet2(t *testing.T) {
arr := NewWithCap(5, 3)
l := []int{0, 6, 5, 14}
for _, v := range l {
arr.Set(v, v)
}
var result string
result = spew.Sprint(arr.debugValues())
if result != "[0 {} {} {} {} 5 6 {} {} <nil> <nil> <nil> {} {} 14]" {
t.Error(result)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the set is out of range")
}
}()
arr.Set(16, 16)
}
func TestArray2Set(t *testing.T) {
testSet1(t)
testSet2(t)
}
func testArray2Get1(t *testing.T) {
arr := New()
for i := 0; i < 64; i++ {
arr.Set(i, i)
}
for i := 0; i < 64; i++ {
if v, ok := arr.Get(i); ok {
if v != i {
t.Error("v is equal i, but", v, i)
}
} else {
t.Error("not ok is error")
}
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the get is out of range")
}
}()
arr.Get(64)
}
func testArray2Get2(t *testing.T) {
arr := NewWithCap(9, 8)
for i := 0; i < 64; i++ {
arr.Set(i, i)
}
for i := 0; i < 64; i++ {
if v, ok := arr.Get(i); ok {
if v != i {
t.Error("v is equal i, but", v, i)
}
} else {
t.Error("not ok is error")
}
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the get is out of range")
}
}()
arr.Get(72)
}
func TestArray2Get(t *testing.T) {
testArray2Get1(t)
testArray2Get2(t)
}
func TestArray2Del(t *testing.T) {
arr := NewWithCap(3, 6)
l := []int{0, 6, 5, 15}
for _, v := range l {
arr.Set(v, v)
}
// default [0 {} {} {} {} 5 6 {} <nil> <nil> <nil> <nil> {} {} {} 15]
var result string
arr.Del(0)
result = spew.Sprint(arr.debugValues())
if result != "[{} {} {} {} {} 5 6 {} {} {} {} {} {} {} {} 15 {} {}]" {
t.Error(arr.data)
t.Error(result)
}
arr.Del(5)
result = spew.Sprint(arr.debugValues())
if result != "[<nil> <nil> <nil> <nil> <nil> <nil> 6 {} {} {} {} {} {} {} {} 15 {} {}]" {
t.Error(arr.data)
t.Error(result)
}
arr.Del(6)
result = spew.Sprint(arr.debugValues())
if result != "[<nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> {} {} {} 15 {} {}]" {
t.Error(result)
}
arr.Del(15)
result = spew.Sprint(arr.debugValues())
if result != "[<nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil>]" {
t.Error(result)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the del is out of range")
}
}()
arr.Del(18)
}
func TestArray2Grow(t *testing.T) {
arr := NewWithCap(4, 4)
l := []int{0, 6, 5, 15}
for _, v := range l {
arr.Set(v, v)
}
arr.Grow(1)
if v, ok := arr.Get(15); ok {
if v != 15 {
t.Error(v)
}
} else {
t.Error(v)
}
arr.Set(19, 19)
if v, ok := arr.Get(19); ok {
if v != 19 {
t.Error(v)
}
} else {
t.Error(v)
}
arr.Grow(-1)
var result string
result = spew.Sprint(arr.debugValues())
if result != "[0 {} {} {} {} 5 6 {} <nil> <nil> <nil> <nil> {} {} {} 15]" {
t.Error(result)
}
}
func BenchmarkArray2Set(b *testing.B) {
arr := NewWithCap(1000, 100)
b.N = 500000000
b.StopTimer()
var l []int
for i := 0; i < b.N/10; i++ {
l = append(l, randomdata.Number(0, 65535))
}
b.StartTimer()
for c := 0; c < 10; c++ {
for i := 0; i < b.N/10; i++ {
arr.Set(l[i], i)
}
}
}
func BenchmarkArray2Get(b *testing.B) {
arr := NewWithCap(1000, 100)
b.N = 500000000
b.StopTimer()
for i := 0; i < 105535; i++ {
v := randomdata.Number(0, 65535)
arr.Set(v, v)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
arr.Get(i % 65535)
}
}
func BenchmarkArray2Del(b *testing.B) {
arr := NewWithCap(1000, 100)
b.N = 500000000
b.StopTimer()
for i := 0; i < 105535; i++ {
v := randomdata.Number(0, 65535)
arr.Set(v, v)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
arr.Del(i % 65535)
}
}

View File

@@ -0,0 +1,232 @@
package array3
type Array3 struct {
ysizes []int
xsizes [][]int
xyproduct int
zsize int
ysize int
xsize int
data [][][]interface{}
cap int
}
func New() *Array3 {
return NewWithCap(8, 8, 8)
}
func NewWithCap(zsize, ysize, xsize int) *Array3 {
arr := &Array3{zsize: zsize, ysize: ysize, xsize: xsize}
arr.ysizes = make([]int, arr.zsize, arr.zsize)
arr.xsizes = make([][]int, arr.zsize, arr.zsize)
for i := 0; i < arr.zsize; i++ {
arr.xsizes[i] = make([]int, arr.ysize, arr.ysize)
}
arr.xyproduct = arr.ysize * arr.xsize
arr.data = make([][][]interface{}, arr.zsize, arr.zsize)
arr.cap = arr.zsize * arr.xyproduct
return arr
}
func (arr *Array3) debugValues() []interface{} {
var result []interface{}
for _, z := range arr.data {
if z != nil {
for _, y := range z {
if y == nil {
for i := 0; i < arr.xsize; i++ {
result = append(result, nil)
}
} else {
for _, x := range y {
if x == nil {
result = append(result, struct{}{})
} else {
result = append(result, x)
}
}
}
}
} else {
for i := 0; i < arr.ysize*arr.xsize; i++ {
result = append(result, nil)
}
}
}
return result
}
func (arr *Array3) Values() []interface{} {
var result []interface{}
for _, z := range arr.data {
if z != nil {
for _, y := range z {
if y == nil {
for i := 0; i < arr.xsize; i++ {
result = append(result, nil)
}
} else {
for _, x := range y {
if x == nil {
result = append(result, nil)
} else {
result = append(result, x)
}
}
}
}
} else {
for i := 0; i < arr.ysize*arr.xsize; i++ {
result = append(result, nil)
}
}
}
return result
}
func (arr *Array3) Cap() int {
return arr.cap
}
func (arr *Array3) Grow(size int) {
zsize := arr.zsize + size
temp := make([][][]interface{}, zsize, zsize)
copy(temp, arr.data)
arr.data = temp
tempysizes := make([]int, zsize, zsize)
copy(tempysizes, arr.ysizes)
arr.ysizes = tempysizes
tempxsizes := make([][]int, zsize, zsize)
copy(tempxsizes, arr.xsizes)
arr.xsizes = tempxsizes
for i := arr.zsize; i < zsize; i++ {
arr.xsizes[i] = make([]int, arr.ysize, arr.ysize)
}
arr.zsize += size
arr.cap = arr.zsize * arr.xyproduct
}
func (arr *Array3) Set(idx int, value interface{}) {
zindex := idx / arr.xyproduct
nidx := (idx % arr.xyproduct)
yindex := nidx / arr.xsize
xindex := nidx % arr.xsize
ydata := arr.data[zindex]
if ydata == nil {
ydata = make([][]interface{}, arr.ysize, arr.ysize)
arr.data[zindex] = ydata
}
xdata := ydata[yindex]
if xdata == nil {
xdata = make([]interface{}, arr.xsize, arr.xsize)
ydata[yindex] = xdata
arr.ysizes[zindex]++
}
v := xdata[xindex]
if v == nil {
arr.xsizes[zindex][yindex]++
}
xdata[xindex] = value
}
func (arr *Array3) Get(idx int) (interface{}, bool) {
zindex := idx / arr.xyproduct
nextsize := (idx % arr.xyproduct)
yindex := nextsize / arr.xsize
xindex := nextsize % arr.xsize
ydata := arr.data[zindex]
if ydata == nil {
return nil, false
}
xdata := ydata[yindex]
if xdata == nil {
return nil, false
}
v := xdata[xindex]
return v, v != nil
}
func (arr *Array3) GetOrSet(idx int, DoSetValue func([]interface{}, int)) (result interface{}, isSet bool) {
zindex := idx / arr.xyproduct
nidx := (idx % arr.xyproduct)
yindex := nidx / arr.xsize
xindex := nidx % arr.xsize
ydata := arr.data[zindex]
if ydata == nil {
ydata = make([][]interface{}, arr.ysize, arr.ysize)
arr.data[zindex] = ydata
}
xdata := ydata[yindex]
if xdata == nil {
xdata = make([]interface{}, arr.xsize, arr.xsize)
ydata[yindex] = xdata
arr.ysizes[zindex]++
}
result = xdata[xindex]
if result == nil {
DoSetValue(xdata, xindex)
result = xdata[xindex]
if result == nil {
panic("DoSetValue Not Set <nil> Value")
}
arr.xsizes[zindex][yindex]++
return result, false
}
return result, true
}
func (arr *Array3) Del(idx int) (interface{}, bool) {
zindex := idx / arr.xyproduct
nextsize := (idx % arr.xyproduct)
yindex := nextsize / arr.xsize
xindex := nextsize % arr.xsize
ydata := arr.data[zindex]
if ydata == nil {
return nil, false
}
xdata := ydata[yindex]
if xdata == nil {
return nil, false
}
v := xdata[xindex]
xdata[xindex] = nil
isnotnil := v != nil
if isnotnil {
arr.xsizes[zindex][yindex]--
if arr.xsizes[zindex][yindex] == 0 {
arr.data[zindex][yindex] = nil
arr.ysizes[zindex]--
if arr.ysizes[zindex] == 0 {
arr.data[zindex] = nil
}
}
}
return v, isnotnil
}

View File

@@ -0,0 +1,215 @@
package array3
import (
"testing"
"github.com/davecgh/go-spew/spew"
"github.com/Pallinder/go-randomdata"
)
func testSet1(t *testing.T) {
arr := NewWithCap(2, 2, 2)
l := []int{0, 1, 7}
for _, v := range l {
arr.Set(v, v)
}
var result string
result = spew.Sprint(arr.debugValues())
if result != "[0 1 <nil> <nil> <nil> <nil> {} 7]" {
t.Error(result)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the set is out of range")
}
}()
arr.Set(8, 8)
}
func testSet2(t *testing.T) {
arr := NewWithCap(2, 2, 3)
l := []int{0, 6, 5, 11}
for _, v := range l {
arr.Set(v, v)
}
var result string
result = spew.Sprint(arr.debugValues())
if result != "[0 {} {} {} {} 5 6 {} {} {} {} 11]" {
t.Error(arr.data)
t.Error(result)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the set is out of range")
}
}()
arr.Set(12, 12)
}
func TestArray2Set(t *testing.T) {
testSet1(t)
testSet2(t)
}
func testArray2Get1(t *testing.T) {
arr := New()
for i := 0; i < 64; i++ {
arr.Set(i, i)
}
for i := 0; i < 64; i++ {
if v, ok := arr.Get(i); ok {
if v != i {
t.Error("v is equal i, but", v, i)
}
} else {
t.Error("not ok is error")
}
}
if v, ok := arr.Get(8*8*8 - 1); ok {
t.Error(v)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the get is out of range")
}
}()
arr.Get(8 * 8 * 8)
}
func testArray2Get2(t *testing.T) {
arr := NewWithCap(4, 3, 3)
for i := 0; i < 36; i++ {
arr.Set(i, i)
}
for i := 0; i < 36; i++ {
if v, ok := arr.Get(i); ok {
if v != i {
t.Error("v is equal i, but", v, i)
}
} else {
t.Error("not ok is error")
}
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the get is out of range")
}
}()
arr.Get(36)
}
func TestArray2Get(t *testing.T) {
testArray2Get1(t)
testArray2Get2(t)
}
func TestArray2Del(t *testing.T) {
arr := NewWithCap(2, 2, 3)
l := []int{0, 6, 5, 11}
for _, v := range l {
arr.Set(v, v)
}
// default [0 {} {} {} {} 5 6 {} <nil> <nil> <nil> <nil> {} {} {} 15]
var result string
arr.Del(0)
result = spew.Sprint(arr.debugValues())
if result != "[<nil> <nil> <nil> {} {} 5 6 {} {} {} {} 11]" {
t.Error(arr.data)
t.Error(result)
}
arr.Del(5)
result = spew.Sprint(arr.debugValues())
if result != "[<nil> <nil> <nil> <nil> <nil> <nil> 6 {} {} {} {} 11]" {
t.Error(arr.data)
t.Error(result)
}
arr.Del(6)
result = spew.Sprint(arr.debugValues())
if result != "[<nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> {} {} 11]" {
t.Error(result)
}
arr.Del(11)
result = spew.Sprint(arr.debugValues())
if result != "[<nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil>]" {
t.Error(result)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the del is out of range")
}
}()
arr.Del(18)
}
func BenchmarkArray3Set(b *testing.B) {
arr := NewWithCap(100, 100, 10)
b.N = 500000000
b.StopTimer()
var l []int
for i := 0; i < b.N/10; i++ {
l = append(l, randomdata.Number(0, 65535))
}
b.StartTimer()
for c := 0; c < 10; c++ {
for i := 0; i < b.N/10; i++ {
arr.Set(l[i], i)
}
}
}
func BenchmarkArray3Get(b *testing.B) {
arr := NewWithCap(100, 100, 10)
b.N = 500000000
b.StopTimer()
for i := 0; i < 105535; i++ {
v := randomdata.Number(0, 65535)
arr.Set(v, v)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
arr.Get(i % 65535)
}
}
func BenchmarkArray3Del(b *testing.B) {
arr := NewWithCap(100, 100, 10)
b.N = 500000000
b.StopTimer()
for i := 0; i < 105535; i++ {
v := randomdata.Number(0, 65535)
arr.Set(v, v)
}
b.StartTimer()
for i := 0; i < b.N; i++ {
arr.Del(i % 65535)
}
}

View File

@@ -0,0 +1,217 @@
package arrayn
type SizeN struct {
Sizes []int
}
type ProductN struct {
Values []int
}
type DimensionSize struct {
Sizes []int
}
type Node struct {
size int
data interface{}
}
type ArrayN struct {
dims []int
product []int
dimN int
data *Node // []*Node
cap int
}
func New() *ArrayN {
return NewWithCap(8, 8, 8)
}
func NewWithCap(dims ...int) *ArrayN {
arr := &ArrayN{dimN: len(dims), dims: dims}
arr.product = make([]int, len(dims)-1, len(dims)-1)
for i := 0; i < len(dims)-1; i++ {
pvalue := 1
for n := i + 1; n < len(dims); n++ {
pvalue *= dims[n]
}
arr.product[i] = pvalue
}
// arr.data = make([]*Node, arr.dims[0], arr.dims[0])
arr.cap = 1
for _, d := range arr.dims {
arr.cap *= d
}
return arr
}
func (arr *ArrayN) collectValues(curDim int, cur *Node, result *[]interface{}) {
if cur == nil {
return
}
if curDim == 1 {
for _, v := range cur.data.([]interface{}) {
if v != nil {
*result = append(*result, v)
} else {
*result = append(*result, nil)
}
}
return
}
for _, n := range cur.data.([]*Node) {
if n != nil {
arr.collectValues(curDim-1, n, result)
} else {
total := 1
for i := len(arr.dims) - curDim + 1; i < len(arr.dims); i++ {
total *= arr.dims[i]
}
for i := 0; i < total; i++ {
*result = append(*result, nil)
}
}
}
}
func (arr *ArrayN) Values() (result []interface{}) {
arr.collectValues(arr.dimN, arr.data, &result)
return
}
func (arr *ArrayN) set(curDim int, curidx int, pdata **Node, parent *Node) (*Node, int) {
sidx := arr.dimN - curDim
if *pdata == nil {
if parent != nil {
parent.size++
}
if curDim > 1 {
*pdata = &Node{data: make([]*Node, arr.dims[sidx], arr.dims[sidx])}
} else {
*pdata = &Node{data: make([]interface{}, arr.dims[sidx], arr.dims[sidx])}
return *pdata, curidx
}
}
cur := *pdata
if curDim == 1 {
return cur, curidx
}
nidx := curidx % arr.product[sidx]
dimindex := curidx / arr.product[sidx]
return arr.set(curDim-1, nidx, &cur.data.([]*Node)[dimindex], cur)
}
func (arr *ArrayN) Cap() int {
return arr.cap
}
func (arr *ArrayN) Grow(size int) {
arr.dims[0] += size
pvalue := 1
for n := 1; n < len(arr.dims); n++ {
pvalue *= arr.dims[n]
}
arr.product[0] = pvalue
tempdata := arr.data.data.([]*Node)
newData := make([]*Node, arr.dims[0], arr.dims[0])
copy(newData, tempdata)
arr.data.data = newData
arr.cap = 1
for _, d := range arr.dims {
arr.cap *= d
}
}
func (arr *ArrayN) Set(idx int, value interface{}) {
n, nidx := arr.set(arr.dimN, idx, &arr.data, nil)
n.data.([]interface{})[nidx] = value
}
func (arr *ArrayN) get(curDim int, curidx int, pdata **Node) (*Node, int) {
sidx := arr.dimN - curDim
if *pdata == nil {
return nil, 0
}
cur := *pdata
if curDim == 1 {
return cur, curidx
}
nidx := curidx % arr.product[sidx]
dimindex := curidx / arr.product[sidx]
return arr.get(curDim-1, nidx, &cur.data.([]*Node)[dimindex])
}
func (arr *ArrayN) Get(idx int) (interface{}, bool) {
n, nidx := arr.get(arr.dimN, idx, &arr.data)
if n != nil {
v := n.data.([]interface{})[nidx]
return v, v != nil
}
return nil, false
}
func (arr *ArrayN) del(curDim int, curidx int, pdata **Node) (interface{}, bool) {
cur := *pdata
if cur == nil {
return nil, false
}
if curDim == 1 {
values := cur.data.([]interface{})
v := values[curidx]
if v != nil {
cur.size--
values[curidx] = nil
if cur.size == 0 {
return v, true
}
}
return v, false
}
sidx := arr.dimN - curDim
nidx := curidx % arr.product[sidx]
dimindex := curidx / arr.product[sidx]
curdata := cur.data.([]*Node)
v, ok := arr.del(curDim-1, nidx, &curdata[dimindex])
if ok {
cur.size--
curdata[dimindex] = nil
if cur.size == 0 {
return v, true
}
}
return v, false
}
func (arr *ArrayN) Del(idx int) (interface{}, bool) {
v, _ := arr.del(arr.dimN, idx, &arr.data)
if v != nil {
return v, true
}
return nil, false
}

View File

@@ -0,0 +1,224 @@
package arrayn
import (
"testing"
"github.com/Pallinder/go-randomdata"
"github.com/davecgh/go-spew/spew"
)
func testSet1(t *testing.T) {
arr := NewWithCap(2, 2, 2)
l := []int{0, 1, 7}
for _, v := range l {
arr.Set(v, v)
}
var result string
result = spew.Sprint(arr.Values())
if result != "[0 1 <nil> <nil> <nil> <nil> <nil> 7]" {
t.Error(result)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the set is out of range")
}
}()
arr.Set(8, 8)
}
func testSet2(t *testing.T) {
arr := NewWithCap(2, 2, 3)
l := []int{0, 6, 5, 11}
for _, v := range l {
arr.Set(v, v)
}
var result string
result = spew.Sprint(arr.Values())
if result != "[0 <nil> <nil> <nil> <nil> 5 6 <nil> <nil> <nil> <nil> 11]" {
t.Error(arr.data)
t.Error(result)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the set is out of range")
}
}()
arr.Set(12, 12)
}
func TestSet(t *testing.T) {
testSet1(t)
testSet2(t)
}
func testArray2Get1(t *testing.T) {
arr := New()
for i := 0; i < 64; i++ {
arr.Set(i, i)
}
for i := 0; i < 64; i++ {
if v, ok := arr.Get(i); ok {
if v != i {
t.Error("v is equal i, but", v, i)
}
} else {
t.Error("not ok is error")
}
}
if v, ok := arr.Get(8*8*8 - 1); ok {
t.Error(v)
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the get is out of range")
}
}()
arr.Get(8 * 8 * 8)
}
func testArray2Get2(t *testing.T) {
arr := NewWithCap(4, 3, 3)
for i := 0; i < 36; i++ {
arr.Set(i, i)
}
for i := 0; i < 36; i++ {
if v, ok := arr.Get(i); ok {
if v != i {
t.Error("v is equal i, but", v, i)
}
} else {
t.Error("not ok is error")
}
}
defer func() {
if err := recover(); err == nil {
t.Error("err == nil, but array the get is out of range")
}
}()
arr.Get(36)
}
func TestArray2Get(t *testing.T) {
testArray2Get1(t)
testArray2Get2(t)
}
func TestDel(t *testing.T) {
arr := NewWithCap(2, 2, 2, 3)
for i := 0; i < 12; i++ {
arr.Set(i, i)
}
arr.Set(23, 23)
for i := 0; i < 12; i++ {
arr.Del(i)
}
arr.Del(23)
var result string
result = spew.Sprint(arr.Values())
if result != "[<nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil>]" {
t.Error("result should be all is nil")
}
}
func TestArray2Grow(t *testing.T) {
arr := NewWithCap(4, 4)
l := []int{0, 6, 5, 15}
for _, v := range l {
arr.Set(v, v)
}
arr.Grow(1)
if v, ok := arr.Get(15); ok {
if v != 15 {
t.Error(v)
}
} else {
t.Error(v)
}
arr.Set(19, 19)
if v, ok := arr.Get(19); ok {
if v != 19 {
t.Error(v)
}
} else {
t.Error(v)
}
arr.Grow(-1)
var result string
result = spew.Sprint(arr.Values())
if result != "[0 <nil> <nil> <nil> <nil> 5 6 <nil> <nil> <nil> <nil> <nil> <nil> <nil> <nil> 15]" {
t.Error(result)
}
}
func BenchmarkGoMap(b *testing.B) {
m := make(map[int]bool)
b.N = 50000000
b.StopTimer()
var l []int
for i := 0; i < b.N/10; i++ {
l = append(l, randomdata.Number(0, 100000000))
}
b.StartTimer()
for c := 0; c < 10; c++ {
for i := 0; i < b.N/10; i++ {
m[l[i]] = true
}
}
}
func BenchmarkArrayNSet(b *testing.B) {
arr := NewWithCap(1000, 10, 10, 100)
b.N = 10000000
b.StopTimer()
var l []int
for i := 0; i < b.N/10; i++ {
l = append(l, randomdata.Number(0, 10000000))
}
b.StartTimer()
for c := 0; c < 10; c++ {
for i := 0; i < b.N/10; i++ {
arr.Set(l[i], i)
}
}
}
func BenchmarkArray3Set(b *testing.B) {
arr := NewWithCap(100, 100, 10)
b.N = 500000000
b.StopTimer()
var l []int
for i := 0; i < b.N/10; i++ {
l = append(l, randomdata.Number(0, 65535))
}
b.StartTimer()
for c := 0; c < 10; c++ {
for i := 0; i < b.N/10; i++ {
arr.Set(l[i], i)
}
}
}

90
stack/stack.go Normal file
View File

@@ -0,0 +1,90 @@
package lastack
import (
"github.com/davecgh/go-spew/spew"
)
type Node struct {
value interface{}
down *Node
}
type Stack struct {
top *Node
size int
}
func New() *Stack {
s := &Stack{}
s.size = 0
return s
}
func (as *Stack) Clear() {
as.size = 0
as.top = nil
}
func (as *Stack) Empty() bool {
return as.size == 0
}
func (as *Stack) Size() int {
return as.size
}
func (as *Stack) String() string {
content := ""
cur := as.top
for ; cur != nil; cur = cur.down {
content += spew.Sprint(cur.value) + " "
}
if len(content) > 0 {
content = content[0 : len(content)-1]
} else {
content = ""
}
return content
}
func (as *Stack) Values() []interface{} {
result := make([]interface{}, as.size, as.size)
cur := as.top
n := 0
for ; cur != nil; cur = cur.down {
result[n] = cur.value
n++
}
return result
}
func (as *Stack) Push(v interface{}) {
nv := &Node{value: v}
nv.down = as.top
as.top = nv
as.size++
}
func (as *Stack) Pop() (interface{}, bool) {
if as.size <= 0 {
return nil, false
}
as.size--
result := as.top
as.top = as.top.down
result.down = nil
return result.value, true
}
func (as *Stack) Peek() (interface{}, bool) {
if as.size <= 0 {
return nil, false
}
return as.top.value, true
}

91
stack/stack_test.go Normal file
View File

@@ -0,0 +1,91 @@
package lastack
import (
"testing"
"github.com/emirpasic/gods/stacks/arraystack"
"github.com/Pallinder/go-randomdata"
)
func BenchmarkPush(b *testing.B) {
s := New()
b.N = 200000
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
}
func BenchmarkGodsPush(b *testing.B) {
s := arraystack.New()
b.N = 200000
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
}
func BenchmarkPop(b *testing.B) {
s := New()
b.N = 200000
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Pop()
}
}
func BenchmarkGodsPop(b *testing.B) {
s := arraystack.New()
b.N = 200000
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Pop()
}
}
func BenchmarkValues(b *testing.B) {
s := New()
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Values()
}
}
func BenchmarkGodsValues(b *testing.B) {
s := arraystack.New()
for i := 0; i < b.N; i++ {
v := randomdata.Number(0, 65535)
s.Push(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
s.Values()
}
}

918
tree/avl/avl.go Normal file
View File

@@ -0,0 +1,918 @@
package avl
import (
"474420502.top/eson/structure/compare"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
children [2]*Node
parent *Node
height int
value interface{}
}
func (n *Node) String() string {
if n == nil {
return "nil"
}
p := "nil"
if n.parent != nil {
p = spew.Sprint(n.parent.value)
}
return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.height) + ")"
}
type Tree struct {
root *Node
size int
Compare compare.Compare
iter *Iterator
}
func New(Compare compare.Compare) *Tree {
return &Tree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)}
}
func (tree *Tree) String() string {
if tree.size == 0 {
return ""
}
str := "AVLTree\n"
output(tree.root, "", true, &str)
return str
}
func (tree *Tree) Iterator() *Iterator {
return initIterator(tree)
}
func (tree *Tree) Size() int {
return tree.size
}
func (tree *Tree) Remove(key interface{}) (interface{}, bool) {
if n, ok := tree.GetNode(key); ok {
tree.size--
if tree.size == 0 {
tree.root = nil
return n.value, true
}
left := getHeight(n.children[0])
right := getHeight(n.children[1])
if left == -1 && right == -1 {
p := n.parent
p.children[getRelationship(n)] = nil
tree.fixRemoveHeight(p)
return n.value, true
}
var cur *Node
if left > right {
cur = n.children[0]
for cur.children[1] != nil {
cur = cur.children[1]
}
cleft := cur.children[0]
cur.parent.children[getRelationship(cur)] = cleft
if cleft != nil {
cleft.parent = cur.parent
}
} else {
cur = n.children[1]
for cur.children[0] != nil {
cur = cur.children[0]
}
cright := cur.children[1]
cur.parent.children[getRelationship(cur)] = cright
if cright != nil {
cright.parent = cur.parent
}
}
cparent := cur.parent
// 修改为interface 交换
n.value, cur.value = cur.value, n.value
// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
if cparent == n {
tree.fixRemoveHeight(n)
} else {
tree.fixRemoveHeight(cparent)
}
return cur.value, true
}
return nil, false
}
func (tree *Tree) Clear() {
tree.size = 0
tree.root = nil
tree.iter = NewIteratorWithCap(nil, 16)
}
// Values 返回先序遍历的值
func (tree *Tree) Values() []interface{} {
mszie := 0
if tree.root != nil {
mszie = tree.size
}
result := make([]interface{}, 0, mszie)
tree.Traversal(func(v interface{}) bool {
result = append(result, v)
return true
}, LDR)
return result
}
func (tree *Tree) GetRange(k1, k2 interface{}) (result []interface{}) {
c := tree.Compare(k2, k1)
switch c {
case 1:
var min, max *Node
resultmin := tree.getArountNode(k1)
resultmax := tree.getArountNode(k2)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if max == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(min)
iter := tree.iter
for iter.Next() {
result = append(result, iter.Value())
if iter.cur == max {
break
}
}
case -1:
var min, max *Node
resultmin := tree.getArountNode(k2)
resultmax := tree.getArountNode(k1)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if min == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(max)
iter := tree.iter
for iter.Prev() {
result = append(result, iter.Value())
if iter.cur == min {
break
}
}
case 0:
if n, ok := tree.GetNode(k1); ok {
return []interface{}{n.value}
}
return []interface{}{}
}
return
}
func (tree *Tree) Get(key interface{}) (interface{}, bool) {
n, ok := tree.GetNode(key)
if ok {
return n.value, true
}
return n, false
}
func (tree *Tree) GetAround(key interface{}) (result [3]interface{}) {
an := tree.getArountNode(key)
for i, n := range an {
if n != nil {
result[i] = n.value
}
}
return
}
func (tree *Tree) getArountNode(key interface{}) (result [3]*Node) {
var last *Node
var lastc int
for n := tree.root; n != nil; {
last = n
c := tree.Compare(key, n.value)
switch c {
case -1:
n = n.children[0]
lastc = c
case 1:
n = n.children[1]
lastc = c
case 0:
tree.iter.SetNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.value, n.value) == 0 {
n = iter.cur
} else {
break
}
}
result[1] = n
n = nil
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
switch lastc {
case 1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[0] = last
result[2] = tree.iter.GetNext(last, 1)
}
case -1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[2] = last
result[0] = tree.iter.GetPrev(last, 1)
}
case 0:
if result[1] == nil {
return
}
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
}
return
}
func (tree *Tree) GetNode(value interface{}) (*Node, bool) {
for n := tree.root; n != nil; {
switch c := tree.Compare(value, n.value); c {
case -1:
n = n.children[0]
case 1:
n = n.children[1]
case 0:
tree.iter.SetNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.value, n.value) == 0 {
n = iter.cur
} else {
break
}
}
return n, true
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
return nil, false
}
func (tree *Tree) Put(value interface{}) {
tree.size++
node := &Node{value: value}
if tree.size == 1 {
tree.root = node
return
}
for cur, c := tree.root, 0; ; {
c = tree.Compare(value, cur.value)
if c == -1 {
if cur.children[0] == nil {
cur.children[0] = node
node.parent = cur
if cur.height == 0 {
tree.fixPutHeight(cur)
}
return
}
cur = cur.children[0]
} else {
if cur.children[1] == nil {
cur.children[1] = node
node.parent = cur
if cur.height == 0 {
tree.fixPutHeight(cur)
}
return
}
cur = cur.children[1]
}
}
}
type TraversalMethod int
const (
// L = left R = right D = Value(dest)
_ TraversalMethod = iota
//DLR 先值 然后左递归 右递归 下面同理
DLR
//LDR 先从左边有序访问到右边 从小到大
LDR
// LRD 同理
LRD
// DRL 同理
DRL
// RDL 先从右边有序访问到左边 从大到小
RDL
// RLD 同理
RLD
)
// Traversal 遍历的方法 默认是LDR 从小到大 Compare 为 l < r
func (tree *Tree) Traversal(every func(v interface{}) bool, traversalMethod ...interface{}) {
if tree.root == nil {
return
}
method := LDR
if len(traversalMethod) != 0 {
method = traversalMethod[0].(TraversalMethod)
}
switch method {
case DLR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LDR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LRD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
case DRL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case RDL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
return true
}
traverasl(tree.root)
case RLD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
}
}
func (tree *Tree) lrrotate(cur *Node) {
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 {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
//mov.children[l].child = l
} else {
mov.children[l] = nil
}
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
// movparent.size = getChildrenSumSize(movparent) + 1
// mov.size = getChildrenSumSize(mov) + 1
// cur.size = getChildrenSumSize(cur) + 1
mov.height = getMaxChildrenHeight(mov) + 1
movparent.height = getMaxChildrenHeight(movparent) + 1
cur.height = getMaxChildrenHeight(cur) + 1
}
func (tree *Tree) rlrotate(cur *Node) {
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 {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
// movparent.size = getChildrenSumSize(movparent) + 1
// mov.size = getChildrenSumSize(mov) + 1
// cur.size = getChildrenSumSize(cur) + 1
mov.height = getMaxChildrenHeight(mov) + 1
movparent.height = getMaxChildrenHeight(movparent) + 1
cur.height = getMaxChildrenHeight(cur) + 1
}
func (tree *Tree) rrotateex(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
if mov == nil {
return
}
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
// mov.children[l]不可能为nil
cur.children[l] = mov.children[l]
if mov.children[l] != nil {
mov.children[l].parent = cur
}
// 解决mov节点孩子转移的问题
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
}
func (tree *Tree) rrotate(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
// 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 {
mov.children[l] = nil
}
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.size = getChildrenSumSize(mov) + 1
// cur.size = getChildrenSumSize(cur) + 1
mov.height = getMaxChildrenHeight(mov) + 1
cur.height = getMaxChildrenHeight(cur) + 1
}
func (tree *Tree) lrotateex(cur *Node) {
const l = 1
const r = 0
mov := cur.children[l]
if mov == nil {
return
}
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
// 不可能为nil
cur.children[l] = mov.children[l]
if mov.children[l] != nil {
mov.children[l].parent = cur
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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.size = getChildrenSumSize(mov) + 1
// cur.size = getChildrenSumSize(cur) + 1
mov.height = getMaxChildrenHeight(mov) + 1
cur.height = getMaxChildrenHeight(cur) + 1
}
func (tree *Tree) lrotate(cur *Node) {
const l = 1
const r = 0
mov := cur.children[l]
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 {
mov.children[l] = nil
}
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.size = getChildrenSumSize(mov) + 1
// cur.size = getChildrenSumSize(cur) + 1
mov.height = getMaxChildrenHeight(mov) + 1
cur.height = getMaxChildrenHeight(cur) + 1
}
func getMaxAndChildrenHeight(cur *Node) (h1, h2, maxh int) {
h1 = getHeight(cur.children[0])
h2 = getHeight(cur.children[1])
if h1 > h2 {
maxh = h1
} else {
maxh = h2
}
return
}
func getMaxChildrenHeight(cur *Node) int {
h1 := getHeight(cur.children[0])
h2 := getHeight(cur.children[1])
if h1 > h2 {
return h1
}
return h2
}
func getHeight(cur *Node) int {
if cur == nil {
return -1
}
return cur.height
}
func (tree *Tree) fixRemoveHeight(cur *Node) {
for {
lefth, rigthh, lrmax := getMaxAndChildrenHeight(cur)
// 判断当前节点是否有变化, 如果没变化的时候, 不需要往上修复
curheight := lrmax + 1
cur.height = curheight
// 计算高度的差值 绝对值大于2的时候需要旋转
diff := lefth - rigthh
if diff < -1 {
r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式
if getHeight(r.children[0]) > getHeight(r.children[1]) {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
if cur.height == curheight {
return
}
}
if cur.parent == nil {
return
}
cur = cur.parent
}
}
func (tree *Tree) fixPutHeight(cur *Node) {
for {
lefth := getHeight(cur.children[0])
rigthh := getHeight(cur.children[1])
// 计算高度的差值 绝对值大于2的时候需要旋转
diff := lefth - rigthh
if diff < -1 {
r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式
if getHeight(r.children[0]) > getHeight(r.children[1]) {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
// 选择一个child的最大高度 + 1为 高度
if lefth > rigthh {
cur.height = lefth + 1
} else {
cur.height = rigthh + 1
}
}
if cur.parent == nil || cur.height < cur.parent.height {
return
}
cur = cur.parent
}
}
func output(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
output(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
*str += spew.Sprint(node.value) + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
output(node.children[0], newPrefix, true, str)
}
}
func outputfordebug(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
outputfordebug(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
suffix := "("
parentv := ""
if node.parent == nil {
parentv = "nil"
} else {
parentv = spew.Sprint(node.parent.value)
}
suffix += parentv + "|" + spew.Sprint(node.height) + ")"
*str += spew.Sprint(node.value) + suffix + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
outputfordebug(node.children[0], newPrefix, true, str)
}
}
func (tree *Tree) debugString() string {
if tree.size == 0 {
return ""
}
str := "AVLTree\n"
outputfordebug(tree.root, "", true, &str)
return str
}

562
tree/avl/avl_test.go Normal file
View File

@@ -0,0 +1,562 @@
package avl
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"474420502.top/eson/structure/compare"
"github.com/Pallinder/go-randomdata"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/avltree"
"github.com/emirpasic/gods/trees/redblacktree"
)
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) {
tree := New(compare.Int)
for _, v := range []int{1, 2, 7, 4, 5, 6, 7, 14, 15, 20, 30, 21, 3} {
// t.Error(v)
tree.Put(v)
}
// ` AVLTree
// │ ┌── 30
// │ │ └── 21
// │ ┌── 20
// │ │ └── 15
// └── 14
// │ ┌── 7
// │ ┌── 7
// │ │ └── 6
// └── 5
// │ ┌── 4
// │ │ └── 3
// └── 2
// └── 1`
iter := tree.Iterator() // root start point
l := []int{14, 15, 20, 21, 30}
for i := 0; iter.Next(); i++ {
if iter.Value().(int) != l[i] {
t.Error("iter Next error", iter.Value(), l[i])
}
}
iter.Next()
if iter.Value().(int) != 30 {
t.Error("Next == false", iter.Value(), iter.Next(), iter.Value())
}
l = []int{21, 20, 15, 14, 7, 7, 6, 5, 4, 3, 2, 1}
for i := 0; iter.Prev(); i++ { // cur is 30 next is 21
if iter.Value().(int) != l[i] {
t.Error(iter.Value())
}
}
if iter.Prev() != false {
t.Error("Prev is error, cur is tail, val = 1 Prev return false")
}
if iter.Value().(int) != 1 { // cur is 1
t.Error("next == false", iter.Value(), iter.Prev(), iter.Value())
}
if iter.Next() != true && iter.Value().(int) != 2 {
t.Error("next to prev is error")
}
}
func TestGetRange(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v)
}
// t.Error(tree.debugString())
// t.Error(tree.getArountNode(20))
// t.Error(tree.Values())
result := tree.GetRange(0, 20)
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(-5, -1)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(7, 20)
if spew.Sprint(result) != "[8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(30, 40)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(30, 60)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(40, 40)
if spew.Sprint(result) != "[40]" {
t.Error(result)
}
result = tree.GetRange(50, 60)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(50, 1)
if spew.Sprint(result) != "[40 30 17 13 10 8 6 5 2 1]" {
t.Error(result)
}
result = tree.GetRange(30, 20)
if spew.Sprint(result) != "[30]" {
t.Error(result)
}
}
func TestGetAround(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
tree.Put(v)
}
var Result string
Result = spew.Sprint(tree.GetAround(14))
if Result != "[7 14 14]" {
t.Error(tree.Values())
t.Error("14 is root, tree.GetAround(14)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(tree.GetAround(17))
if Result != "[16 17 20]" {
t.Error(tree.Values())
t.Error("tree.GetAround(17)) is error", Result)
t.Error(tree.debugString())
}
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(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 != "[17 <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> 7]" {
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
func TestPutStable(t *testing.T) {
// f, _ := os.OpenFile("./test.log", os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666)
// log.SetOutput(f)
// 0-1 3 | 2-3 7-8 | 4-7 12-16 | 8-15 20-32 | 16-31 33-58 l := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 18, 19, 20, 21, 22, 30, 41, 41, 41}
// tree := New(compare.Int)
// for i := 0; i < 10; i++ {
// tree.Put(randomdata.Number(0, 100))
// }
// t.Error(tree.debugString())
// t.Error(tree.debugString(), tree.TraversalBreadth(), "\n", "-----------")
}
func TestPutComparatorRandom(t *testing.T) {
for n := 0; n < 300000; n++ {
tree := New(compare.Int)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 10; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + ","
tree.Put(v)
godsavl.Put(v, v)
}
}
if tree.String() != godsavl.String() {
t.Error(godsavl.String())
t.Error(tree.debugString())
t.Error(content, n)
break
}
}
}
func TestGet(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
tree.Put(v)
}
result := `
│ ┌── 57092
│ ┌── 39016
│ │ └── 36513
│ ┌── 27897
│ │ │ ┌── 23202
│ │ └── 22574
└── 7666
│ ┌── 3055
└── 2383
└── 1562
`
s1 := tree.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 := tree.Get(v)
if !ok {
t.Error("the val not found ", v)
}
}
if v, ok := tree.Get(10000); ok {
t.Error("the val(10000) is not in tree, but is found", v)
}
}
func TestRemoveAll(t *testing.T) {
ALL:
for c := 0; c < 50000; c++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 50; i++ {
v := randomdata.Number(0, 100000)
if _, ok := m[v]; !ok {
m[v] = v
l = append(l, v)
tree.Put(v)
gods.Put(v, v)
}
}
for i := 0; i < 50; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(gods.Values())
if s1 != s2 {
t.Error("avl remove error", "avlsize = ", tree.Size())
t.Error(s1)
t.Error(s2)
break ALL
}
}
}
}
func TestRemove(t *testing.T) {
ALL:
for N := 0; N < 500000; N++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 10; i++ {
v := randomdata.Number(0, 100)
if _, ok := m[v]; !ok {
l = append(l, v)
m[v] = v
tree.Put(v)
gods.Put(v, v)
}
}
src1 := tree.String()
src2 := gods.String()
for i := 0; i < 10; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
if spew.Sprint(gods.Values()) != spew.Sprint(tree.Values()) && tree.size != 0 {
// if gods.String() != tree.String() && gods.Size() != 0 && tree.size != 0 {
t.Error(src1)
t.Error(src2)
t.Error(tree.debugString())
t.Error(gods.String())
t.Error(l[i])
// t.Error(tree.TraversalDepth(-1))
// t.Error(gods.Values())
break ALL
}
}
}
}
func BenchmarkIterator(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
for _, v := range l {
tree.Put(v)
}
b.ResetTimer()
b.StartTimer()
b.N = 0
iter := tree.Iterator()
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
}
func BenchmarkRemove(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < len(l); i++ {
tree.Remove(l[i])
}
}
func BenchmarkGodsRemove(b *testing.B) {
tree := avltree.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 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) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsRBGet(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsAvlGet(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkPut(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 50
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
tree := New(compare.Int)
for _, v := range l {
tree.Put(v)
}
}
// b.Log(tree.count)
}
func BenchmarkGodsRBPut(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}
func BenchmarkGodsPut(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}

229
tree/avl/iterator.go Normal file
View File

@@ -0,0 +1,229 @@
package avl
import (
"474420502.top/eson/structure/lastack"
)
type Iterator struct {
dir int
up *Node
cur *Node
tstack *lastack.Stack
// curnext *Node
}
func initIterator(avltree *Tree) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = avltree.root
return iter
}
func NewIterator(n *Node) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = n
return iter
}
func NewIteratorWithCap(n *Node, cap int) *Iterator {
iter := &Iterator{tstack: lastack.NewWithCap(cap)}
iter.up = n
return iter
}
func (iter *Iterator) SetNode(n *Node) {
iter.up = n
iter.dir = 0
iter.tstack.Clear()
}
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) GetNext(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushNextStack(iter.up)
iter.up = iter.getNextUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getNextUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushNextStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Next() (result bool) {
if iter.dir > -1 {
if iter.dir == 1 && iter.cur != nil {
iter.tstack.Clear()
iter.curPushNextStack(iter.cur)
iter.up = iter.getNextUp(iter.cur)
}
iter.dir = -1
}
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
}
return false
}
func (iter *Iterator) GetPrev(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushPrevStack(iter.up)
iter.up = iter.getPrevUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushPrevStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Prev() (result bool) {
if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev)
if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈
iter.tstack.Clear()
iter.curPushPrevStack(iter.cur) // 把当前cur计算的逆向回朔
iter.up = iter.getPrevUp(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.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
iter.curPushPrevStack(iter.cur)
return true
}
// 如果再次计算的栈为空, 则只能返回false
return false
}
func getRelationship(cur *Node) int {
if cur.parent.children[1] == cur {
return 1
}
return 0
}
func (iter *Iterator) getPrevUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushPrevStack(cur *Node) {
Prev := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值
if Prev != nil {
iter.tstack.Push(Prev)
for Prev.children[1] != nil {
Prev = Prev.children[1]
iter.tstack.Push(Prev) // 入栈 用于回溯
}
}
}
func (iter *Iterator) getNextUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushNextStack(cur *Node) {
next := cur.children[1]
if next != nil {
iter.tstack.Push(next)
for next.children[0] != nil {
next = next.children[0]
iter.tstack.Push(next)
}
}
}

888
tree/avldup/avldup.go Normal file
View File

@@ -0,0 +1,888 @@
package avldup
import (
"474420502.top/eson/structure/compare"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
children [2]*Node
parent *Node
height int
value interface{}
}
func (n *Node) String() string {
if n == nil {
return "nil"
}
p := "nil"
if n.parent != nil {
p = spew.Sprint(n.parent.value)
}
return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.height) + ")"
}
type Tree struct {
root *Node
size int
Compare compare.Compare
iter *Iterator
}
func New(Compare compare.Compare) *Tree {
return &Tree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)}
}
func (tree *Tree) String() string {
if tree.size == 0 {
return ""
}
str := "AVLTree\n"
output(tree.root, "", true, &str)
return str
}
func (tree *Tree) Iterator() *Iterator {
return initIterator(tree)
}
func (tree *Tree) Size() int {
return tree.size
}
func (tree *Tree) Remove(key interface{}) (interface{}, bool) {
if n, ok := tree.GetNode(key); ok {
tree.size--
if tree.size == 0 {
tree.root = nil
return n.value, true
}
left := getHeight(n.children[0])
right := getHeight(n.children[1])
if left == -1 && right == -1 {
p := n.parent
p.children[getRelationship(n)] = nil
tree.fixRemoveHeight(p)
return n.value, true
}
var cur *Node
if left > right {
cur = n.children[0]
for cur.children[1] != nil {
cur = cur.children[1]
}
cleft := cur.children[0]
cur.parent.children[getRelationship(cur)] = cleft
if cleft != nil {
cleft.parent = cur.parent
}
} else {
cur = n.children[1]
for cur.children[0] != nil {
cur = cur.children[0]
}
cright := cur.children[1]
cur.parent.children[getRelationship(cur)] = cright
if cright != nil {
cright.parent = cur.parent
}
}
cparent := cur.parent
// 修改为interface 交换
n.value, cur.value = cur.value, n.value
// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
if cparent == n {
tree.fixRemoveHeight(n)
} else {
tree.fixRemoveHeight(cparent)
}
return cur.value, true
}
return nil, false
}
func (tree *Tree) Clear() {
tree.size = 0
tree.root = nil
tree.iter = NewIteratorWithCap(nil, 16)
}
// Values 返回先序遍历的值
func (tree *Tree) Values() []interface{} {
mszie := 0
if tree.root != nil {
mszie = tree.size
}
result := make([]interface{}, 0, mszie)
tree.Traversal(func(v interface{}) bool {
result = append(result, v)
return true
}, LDR)
return result
}
func (tree *Tree) GetRange(k1, k2 interface{}) (result []interface{}) {
c := tree.Compare(k2, k1)
switch c {
case 1:
var min, max *Node
resultmin := tree.getArountNode(k1)
resultmax := tree.getArountNode(k2)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if max == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(min)
iter := tree.iter
for iter.Next() {
result = append(result, iter.Value())
if iter.cur == max {
break
}
}
case -1:
var min, max *Node
resultmin := tree.getArountNode(k2)
resultmax := tree.getArountNode(k1)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if min == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(max)
iter := tree.iter
for iter.Prev() {
result = append(result, iter.Value())
if iter.cur == min {
break
}
}
case 0:
if n, ok := tree.GetNode(k1); ok {
return []interface{}{n.value}
}
return []interface{}{}
}
return
}
func (tree *Tree) Get(key interface{}) (interface{}, bool) {
n, ok := tree.GetNode(key)
if ok {
return n.value, true
}
return n, false
}
func (tree *Tree) GetAround(key interface{}) (result [3]interface{}) {
an := tree.getArountNode(key)
for i, n := range an {
if n != nil {
result[i] = n.value
}
}
return
}
func (tree *Tree) getArountNode(key interface{}) (result [3]*Node) {
var last *Node
var lastc int
for n := tree.root; n != nil; {
last = n
c := tree.Compare(key, 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 Compare only is allowed in -1, 0, 1")
}
}
switch lastc {
case 1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[0] = last
result[2] = tree.iter.GetNext(last, 1)
}
case -1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[2] = last
result[0] = tree.iter.GetPrev(last, 1)
}
case 0:
if result[1] == nil {
return
}
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
}
return
}
func (tree *Tree) GetNode(value interface{}) (*Node, bool) {
for n := tree.root; n != nil; {
switch c := tree.Compare(value, n.value); c {
case -1:
n = n.children[0]
case 1:
n = n.children[1]
case 0:
return n, true
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
return nil, false
}
func (tree *Tree) Put(key interface{}) {
if tree.size == 0 {
tree.root = &Node{value: key}
tree.size++
return
}
for cur, c := tree.root, 0; ; {
c = tree.Compare(key, cur.value)
if c == -1 {
if cur.children[0] == nil {
tree.size++
cur.children[0] = &Node{value: key}
cur.children[0].parent = cur
if cur.height == 0 {
tree.fixPutHeight(cur)
}
return
}
cur = cur.children[0]
} else if c == 1 {
if cur.children[1] == nil {
tree.size++
cur.children[1] = &Node{value: key}
cur.children[1].parent = cur
if cur.height == 0 {
tree.fixPutHeight(cur)
}
return
}
cur = cur.children[1]
} else {
cur.value = key
return
}
}
}
type TraversalMethod int
const (
// L = left R = right D = Value(dest)
_ TraversalMethod = iota
//DLR 先值 然后左递归 右递归 下面同理
DLR
//LDR 先从左边有序访问到右边 从小到大
LDR
// LRD 同理
LRD
// DRL 同理
DRL
// RDL 先从右边有序访问到左边 从大到小
RDL
// RLD 同理
RLD
)
// Traversal 遍历的方法 默认是LDR 从小到大 Compare 为 l < r
func (tree *Tree) Traversal(every func(v interface{}) bool, traversalMethod ...interface{}) {
if tree.root == nil {
return
}
method := LDR
if len(traversalMethod) != 0 {
method = traversalMethod[0].(TraversalMethod)
}
switch method {
case DLR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LDR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LRD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
case DRL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case RDL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
return true
}
traverasl(tree.root)
case RLD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
}
}
func (tree *Tree) lrrotate(cur *Node) {
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 {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
//mov.children[l].child = l
} else {
mov.children[l] = nil
}
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
// movparent.size = getChildrenSumSize(movparent) + 1
// mov.size = getChildrenSumSize(mov) + 1
// cur.size = getChildrenSumSize(cur) + 1
mov.height = getMaxChildrenHeight(mov) + 1
movparent.height = getMaxChildrenHeight(movparent) + 1
cur.height = getMaxChildrenHeight(cur) + 1
}
func (tree *Tree) rlrotate(cur *Node) {
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 {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
}
func (tree *Tree) rrotateex(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
if mov == nil {
return
}
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
// mov.children[l]不可能为nil
cur.children[l] = mov.children[l]
if mov.children[l] != nil {
mov.children[l].parent = cur
}
// 解决mov节点孩子转移的问题
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
}
func (tree *Tree) rrotate(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
// 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 {
mov.children[l] = nil
}
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
}
func (tree *Tree) lrotateex(cur *Node) {
const l = 1
const r = 0
mov := cur.children[l]
if mov == nil {
return
}
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
// 不可能为nil
cur.children[l] = mov.children[l]
if mov.children[l] != nil {
mov.children[l].parent = cur
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
}
func (tree *Tree) lrotate(cur *Node) {
const l = 1
const r = 0
mov := cur.children[l]
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 {
mov.children[l] = nil
}
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
}
func getMaxAndChildrenHeight(cur *Node) (h1, h2, maxh int) {
h1 = getHeight(cur.children[0])
h2 = getHeight(cur.children[1])
if h1 > h2 {
maxh = h1
} else {
maxh = h2
}
return
}
func getMaxChildrenHeight(cur *Node) int {
h1 := getHeight(cur.children[0])
h2 := getHeight(cur.children[1])
if h1 > h2 {
return h1
}
return h2
}
func getHeight(cur *Node) int {
if cur == nil {
return -1
}
return cur.height
}
func (tree *Tree) fixRemoveHeight(cur *Node) {
for {
lefth, rigthh, lrmax := getMaxAndChildrenHeight(cur)
// 判断当前节点是否有变化, 如果没变化的时候, 不需要往上修复
curheight := lrmax + 1
cur.height = curheight
// 计算高度的差值 绝对值大于2的时候需要旋转
diff := lefth - rigthh
if diff < -1 {
r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式
if getHeight(r.children[0]) > getHeight(r.children[1]) {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
if cur.height == curheight {
return
}
}
if cur.parent == nil {
return
}
cur = cur.parent
}
}
func (tree *Tree) fixPutHeight(cur *Node) {
for {
lefth := getHeight(cur.children[0])
rigthh := getHeight(cur.children[1])
// 计算高度的差值 绝对值大于2的时候需要旋转
diff := lefth - rigthh
if diff < -1 {
r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式
if getHeight(r.children[0]) > getHeight(r.children[1]) {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
// 选择一个child的最大高度 + 1为 高度
if lefth > rigthh {
cur.height = lefth + 1
} else {
cur.height = rigthh + 1
}
}
if cur.parent == nil || cur.height < cur.parent.height {
return
}
cur = cur.parent
}
}
func output(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
output(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
*str += spew.Sprint(node.value) + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
output(node.children[0], newPrefix, true, str)
}
}
func outputfordebug(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
outputfordebug(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
suffix := "("
parentv := ""
if node.parent == nil {
parentv = "nil"
} else {
parentv = spew.Sprint(node.parent.value)
}
suffix += parentv + "|" + spew.Sprint(node.height) + ")"
*str += spew.Sprint(node.value) + suffix + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
outputfordebug(node.children[0], newPrefix, true, str)
}
}
func (tree *Tree) debugString() string {
if tree.size == 0 {
return ""
}
str := "AVLTree\n"
outputfordebug(tree.root, "", true, &str)
return str
}

486
tree/avldup/avldup_test.go Normal file
View File

@@ -0,0 +1,486 @@
package avldup
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"474420502.top/eson/structure/compare"
"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 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 TestGetRange(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v)
}
// t.Error(tree.debugString())
// t.Error(tree.getArountNode(20))
// t.Error(tree.Values())
result := tree.GetRange(0, 20)
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(-5, -1)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(7, 20)
if spew.Sprint(result) != "[8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(30, 40)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(30, 60)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(40, 40)
if spew.Sprint(result) != "[40]" {
t.Error(result)
}
result = tree.GetRange(50, 60)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(50, 1)
if spew.Sprint(result) != "[40 30 17 13 10 8 6 5 2 1]" {
t.Error(result)
}
result = tree.GetRange(30, 20)
if spew.Sprint(result) != "[30]" {
t.Error(result)
}
}
func TestGetAround(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
tree.Put(v)
}
var Result string
Result = spew.Sprint(tree.GetAround(14))
if Result != "[7 14 15]" {
t.Error(tree.Values())
t.Error("17 is root, tree.GetAround(14)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(tree.GetAround(17))
if Result != "[16 17 20]" {
t.Error(tree.Values())
t.Error("tree.GetAround(17)) is error", Result)
t.Error(tree.debugString())
}
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(tree.GetAround(40))
if Result != "[30 40 50]" {
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 != "[17 <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> 7]" {
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
func TestPutStable(t *testing.T) {
// t.Error(tree.debugString(), tree.TraversalBreadth(), "\n", "-----------")
}
func TestPutComparatorRandom(t *testing.T) {
for n := 0; n < 300000; n++ {
tree := New(compare.Int)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 10; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + ","
tree.Put(v)
godsavl.Put(v, v)
}
}
if tree.String() != godsavl.String() {
t.Error(godsavl.String())
t.Error(tree.debugString())
t.Error(content, n)
break
}
}
}
func TestGet(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
tree.Put(v)
}
result := `
│ ┌── 57092
│ ┌── 39016
│ │ └── 36513
│ ┌── 27897
│ │ │ ┌── 23202
│ │ └── 22574
└── 7666
│ ┌── 3055
└── 2383
└── 1562
`
s1 := tree.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 := tree.Get(v)
if !ok {
t.Error("the val not found ", v)
}
}
if v, ok := tree.Get(10000); ok {
t.Error("the val(10000) is not in tree, but is found", v)
}
}
func TestRemoveAll(t *testing.T) {
ALL:
for c := 0; c < 5000; c++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 100; i++ {
v := randomdata.Number(0, 100000)
if _, ok := m[v]; !ok {
m[v] = v
l = append(l, v)
tree.Put(v)
gods.Put(v, v)
}
}
for i := 0; i < 100; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(gods.Values())
if s1 != s2 {
t.Error("avl remove error", "avlsize = ", tree.Size())
t.Error(s1)
t.Error(s2)
break ALL
}
}
}
}
func TestRemove(t *testing.T) {
ALL:
for N := 0; N < 500000; N++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 10; i++ {
v := randomdata.Number(0, 100)
if _, ok := m[v]; !ok {
l = append(l, v)
m[v] = v
tree.Put(v)
gods.Put(v, v)
}
}
src1 := tree.String()
src2 := gods.String()
for i := 0; i < 10; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
if spew.Sprint(gods.Values()) != spew.Sprint(tree.Values()) && tree.size != 0 {
// if gods.String() != tree.String() && gods.Size() != 0 && tree.size != 0 {
t.Error(src1)
t.Error(src2)
t.Error(tree.debugString())
t.Error(gods.String())
t.Error(l[i])
// t.Error(tree.TraversalDepth(-1))
// t.Error(gods.Values())
break ALL
}
}
}
}
func BenchmarkIterator(b *testing.B) {
tree := New(utils.IntComparator)
l := loadTestData()
for _, v := range l {
tree.Put(v)
}
b.ResetTimer()
b.StartTimer()
b.N = 0
iter := tree.Iterator()
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
}
func BenchmarkRemove(b *testing.B) {
tree := New(utils.IntComparator)
l := loadTestData()
for _, v := range l {
tree.Put(v)
}
ll := tree.Values()
b.N = len(ll)
b.ResetTimer()
b.StartTimer()
for i := 0; i < len(ll); i++ {
tree.Remove(l[i])
}
}
func BenchmarkGodsRemove(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
ll := tree.Values()
b.N = len(ll)
b.ResetTimer()
b.StartTimer()
for i := 0; i < len(ll); 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)
}
ll := tree.Values()
b.N = len(ll)
b.ResetTimer()
b.StartTimer()
for i := 0; i < len(ll); i++ {
tree.Remove(l[i])
}
}
func BenchmarkGet(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsRBGet(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
tree.Get(l[i])
}
}
func BenchmarkGodsAvlGet(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
tree.Get(l[i])
}
}
func BenchmarkPut(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 1000
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
tree := New(compare.Int)
for _, v := range l {
tree.Put(v)
}
}
// b.Log(tree.count)
}
func BenchmarkGodsRBPut(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}
func BenchmarkGodsPut(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}

229
tree/avldup/iterator.go Normal file
View File

@@ -0,0 +1,229 @@
package avldup
import (
"474420502.top/eson/structure/lastack"
)
type Iterator struct {
dir int
up *Node
cur *Node
tstack *lastack.Stack
// curnext *Node
}
func initIterator(avltree *Tree) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = avltree.root
return iter
}
func NewIterator(n *Node) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = n
return iter
}
func NewIteratorWithCap(n *Node, cap int) *Iterator {
iter := &Iterator{tstack: lastack.NewWithCap(cap)}
iter.up = n
return iter
}
func (iter *Iterator) SetNode(n *Node) {
iter.up = n
iter.dir = 0
iter.tstack.Clear()
}
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) GetNext(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushNextStack(iter.up)
iter.up = iter.getNextUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getNextUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushNextStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Next() (result bool) {
if iter.dir > -1 {
if iter.dir == 1 && iter.cur != nil {
iter.tstack.Clear()
iter.curPushNextStack(iter.cur)
iter.up = iter.getNextUp(iter.cur)
}
iter.dir = -1
}
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
}
return false
}
func (iter *Iterator) GetPrev(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushPrevStack(iter.up)
iter.up = iter.getPrevUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushPrevStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Prev() (result bool) {
if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev)
if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈
iter.tstack.Clear()
iter.curPushPrevStack(iter.cur) // 把当前cur计算的逆向回朔
iter.up = iter.getPrevUp(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.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
iter.curPushPrevStack(iter.cur)
return true
}
// 如果再次计算的栈为空, 则只能返回false
return false
}
func getRelationship(cur *Node) int {
if cur.parent.children[1] == cur {
return 1
}
return 0
}
func (iter *Iterator) getPrevUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushPrevStack(cur *Node) {
Prev := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值
if Prev != nil {
iter.tstack.Push(Prev)
for Prev.children[1] != nil {
Prev = Prev.children[1]
iter.tstack.Push(Prev) // 入栈 用于回溯
}
}
}
func (iter *Iterator) getNextUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushNextStack(cur *Node) {
next := cur.children[1]
if next != nil {
iter.tstack.Push(next)
for next.children[0] != nil {
next = next.children[0]
iter.tstack.Push(next)
}
}
}

829
tree/avlkey/avlkey.go Normal file
View File

@@ -0,0 +1,829 @@
package avlkey
import (
"474420502.top/eson/structure/compare"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
children [2]*Node
parent *Node
height int
key, value interface{}
}
func (n *Node) String() string {
if n == nil {
return "nil"
}
p := "nil"
if n.parent != nil {
p = spew.Sprint(n.parent.value)
}
return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.height) + ")"
}
type Tree struct {
root *Node
size int
Compare compare.Compare
iter *Iterator
}
func New(Compare compare.Compare) *Tree {
return &Tree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)}
}
func (tree *Tree) String() string {
if tree.size == 0 {
return ""
}
str := "AVLTree\n"
output(tree.root, "", true, &str)
return str
}
func (tree *Tree) Iterator() *Iterator {
return initIterator(tree)
}
func (tree *Tree) Size() int {
return tree.size
}
func (tree *Tree) Remove(key interface{}) (interface{}, bool) {
if n, ok := tree.GetNode(key); ok {
tree.size--
if tree.size == 0 {
tree.root = nil
return n.value, true
}
left := getHeight(n.children[0])
right := getHeight(n.children[1])
if left == -1 && right == -1 {
p := n.parent
p.children[getRelationship(n)] = nil
tree.fixRemoveHeight(p)
return n.value, true
}
var cur *Node
if left > right {
cur = n.children[0]
for cur.children[1] != nil {
cur = cur.children[1]
}
cleft := cur.children[0]
cur.parent.children[getRelationship(cur)] = cleft
if cleft != nil {
cleft.parent = cur.parent
}
} else {
cur = n.children[1]
for cur.children[0] != nil {
cur = cur.children[0]
}
cright := cur.children[1]
cur.parent.children[getRelationship(cur)] = cright
if cright != nil {
cright.parent = cur.parent
}
}
cparent := cur.parent
// 修改为interface 交换
n.value, cur.value = cur.value, n.value
n.key, cur.key = cur.key, n.key
// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
if cparent == n {
tree.fixRemoveHeight(n)
} else {
tree.fixRemoveHeight(cparent)
}
return cur.value, true
}
return nil, false
}
func (tree *Tree) Clear() {
tree.size = 0
tree.root = nil
tree.iter = NewIteratorWithCap(nil, 16)
}
// Values 返回先序遍历的值
func (tree *Tree) Values() []interface{} {
mszie := 0
if tree.root != nil {
mszie = tree.size
}
result := make([]interface{}, 0, mszie)
tree.Traversal(func(k, v interface{}) bool {
result = append(result, v)
return true
}, LDR)
return result
}
func (tree *Tree) GetRange(k1, k2 interface{}) (result []interface{}) {
c := tree.Compare(k2, k1)
switch c {
case 1:
var min, max *Node
resultmin := tree.getArountNode(k1)
resultmax := tree.getArountNode(k2)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if max == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(min)
iter := tree.iter
for iter.Next() {
result = append(result, iter.Value())
if iter.cur == max {
break
}
}
case -1:
var min, max *Node
resultmin := tree.getArountNode(k2)
resultmax := tree.getArountNode(k1)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if min == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(max)
iter := tree.iter
for iter.Prev() {
result = append(result, iter.Value())
if iter.cur == min {
break
}
}
case 0:
if n, ok := tree.GetNode(k1); ok {
return []interface{}{n.value}
}
return []interface{}{}
}
return
}
func (tree *Tree) Get(key interface{}) (interface{}, bool) {
n, ok := tree.GetNode(key)
if ok {
return n.value, true
}
return n, false
}
func (tree *Tree) GetAround(key interface{}) (result [3]interface{}) {
an := tree.getArountNode(key)
for i, n := range an {
if n != nil {
result[i] = n.value
}
}
return
}
func (tree *Tree) getArountNode(key interface{}) (result [3]*Node) {
var last *Node
var lastc int
for n := tree.root; n != nil; {
last = n
c := tree.Compare(key, n.key)
switch c {
case -1:
n = n.children[0]
lastc = c
case 1:
n = n.children[1]
lastc = c
case 0:
tree.iter.SetNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.key, n.key) == 0 {
n = iter.cur
} else {
break
}
}
result[1] = n
n = nil
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
switch lastc {
case 1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[0] = last
result[2] = tree.iter.GetNext(last, 1)
}
case -1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[2] = last
result[0] = tree.iter.GetPrev(last, 1)
}
case 0:
if result[1] == nil {
return
}
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
}
return
}
func (tree *Tree) GetNode(key interface{}) (*Node, bool) {
for n := tree.root; n != nil; {
switch c := tree.Compare(key, n.key); c {
case -1:
n = n.children[0]
case 1:
n = n.children[1]
case 0:
tree.iter.SetNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.key, n.key) == 0 {
n = iter.cur
} else {
break
}
}
return n, true
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
return nil, false
}
func (tree *Tree) Put(key, value interface{}) {
tree.size++
node := &Node{key: key, value: value}
if tree.size == 1 {
tree.root = node
return
}
for cur, c := tree.root, 0; ; {
c = tree.Compare(key, cur.key)
if c == -1 {
if cur.children[0] == nil {
cur.children[0] = node
cur.children[0].parent = cur
if cur.height == 0 {
tree.fixPutHeight(cur)
}
return
}
cur = cur.children[0]
} else {
if cur.children[1] == nil {
cur.children[1] = node
cur.children[1].parent = cur
if cur.height == 0 {
tree.fixPutHeight(cur)
}
return
}
cur = cur.children[1]
}
}
}
type TraversalMethod int
const (
// L = left R = right D = Value(dest)
_ TraversalMethod = iota
//DLR 先值 然后左递归 右递归 下面同理
DLR
//LDR 先从左边有序访问到右边 从小到大
LDR
// LRD 同理
LRD
// DRL 同理
DRL
// RDL 先从右边有序访问到左边 从大到小
RDL
// RLD 同理
RLD
)
// Traversal 遍历的方法 默认是LDR 从小到大 Compare 为 l < r
func (tree *Tree) Traversal(every func(k, v interface{}) bool, traversalMethod ...interface{}) {
if tree.root == nil {
return
}
method := LDR
if len(traversalMethod) != 0 {
method = traversalMethod[0].(TraversalMethod)
}
switch method {
case DLR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LDR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LRD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
return true
}
traverasl(tree.root)
case DRL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case RDL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
return true
}
traverasl(tree.root)
case RLD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
return true
}
traverasl(tree.root)
}
}
func (tree *Tree) lrrotate(cur *Node) {
const l = 1
const r = 0
movparent := cur.children[l]
mov := movparent.children[r]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
mov.key, cur.key = cur.key, mov.key
if mov.children[l] != nil {
movparent.children[r] = mov.children[l]
movparent.children[r].parent = movparent
//movparent.children[r].child = l
} else {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
//mov.children[l].child = l
} else {
mov.children[l] = nil
}
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
}
func (tree *Tree) rlrotate(cur *Node) {
const l = 0
const r = 1
movparent := cur.children[l]
mov := movparent.children[r]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
mov.key, cur.key = cur.key, mov.key
if mov.children[l] != nil {
movparent.children[r] = mov.children[l]
movparent.children[r].parent = movparent
} else {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
}
func (tree *Tree) rrotate(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
mov.key, cur.key = cur.key, mov.key
// 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 {
mov.children[l] = nil
}
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
}
func (tree *Tree) lrotate(cur *Node) {
const l = 1
const r = 0
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
mov.key, cur.key = cur.key, mov.key
// 不可能为nil
mov.children[l].parent = cur
cur.children[l] = mov.children[l]
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
}
func getMaxAndChildrenHeight(cur *Node) (h1, h2, maxh int) {
h1 = getHeight(cur.children[0])
h2 = getHeight(cur.children[1])
if h1 > h2 {
maxh = h1
} else {
maxh = h2
}
return
}
func getMaxChildrenHeight(cur *Node) int {
h1 := getHeight(cur.children[0])
h2 := getHeight(cur.children[1])
if h1 > h2 {
return h1
}
return h2
}
func getHeight(cur *Node) int {
if cur == nil {
return -1
}
return cur.height
}
func (tree *Tree) fixRemoveHeight(cur *Node) {
for {
lefth, rigthh, lrmax := getMaxAndChildrenHeight(cur)
// 判断当前节点是否有变化, 如果没变化的时候, 不需要往上修复
curheight := lrmax + 1
cur.height = curheight
// 计算高度的差值 绝对值大于2的时候需要旋转
diff := lefth - rigthh
if diff < -1 {
r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式
if getHeight(r.children[0]) > getHeight(r.children[1]) {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
if cur.height == curheight {
return
}
}
if cur.parent == nil {
return
}
cur = cur.parent
}
}
func (tree *Tree) fixPutHeight(cur *Node) {
for {
lefth := getHeight(cur.children[0])
rigthh := getHeight(cur.children[1])
// 计算高度的差值 绝对值大于2的时候需要旋转
diff := lefth - rigthh
if diff < -1 {
r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式
if getHeight(r.children[0]) > getHeight(r.children[1]) {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
// 选择一个child的最大高度 + 1为 高度
if lefth > rigthh {
cur.height = lefth + 1
} else {
cur.height = rigthh + 1
}
}
if cur.parent == nil || cur.height < cur.parent.height {
return
}
cur = cur.parent
}
}
func output(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
output(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
*str += spew.Sprint(node.value) + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
output(node.children[0], newPrefix, true, str)
}
}
func outputfordebug(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
outputfordebug(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
suffix := "("
parentv := ""
if node.parent == nil {
parentv = "nil"
} else {
parentv = spew.Sprint(node.parent.value)
}
suffix += parentv + "|" + spew.Sprint(node.height) + ")"
*str += spew.Sprint(node.value) + suffix + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
outputfordebug(node.children[0], newPrefix, true, str)
}
}
func (tree *Tree) debugString() string {
if tree.size == 0 {
return ""
}
str := "AVLTree\n"
outputfordebug(tree.root, "", true, &str)
return str
}

563
tree/avlkey/avlkey_test.go Normal file
View File

@@ -0,0 +1,563 @@
package avlkey
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"474420502.top/eson/structure/compare"
"github.com/Pallinder/go-randomdata"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/avltree"
"github.com/emirpasic/gods/trees/redblacktree"
)
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) {
tree := New(compare.Int)
for _, v := range []int{1, 2, 7, 4, 5, 6, 7, 14, 15, 20, 30, 21, 3} {
// t.Error(v)
tree.Put(v, v)
}
// ` AVLTree
// │ ┌── 30
// │ │ └── 21
// │ ┌── 20
// │ │ └── 15
// └── 14
// │ ┌── 7
// │ ┌── 7
// │ │ └── 6
// └── 5
// │ ┌── 4
// │ │ └── 3
// └── 2
// └── 1`
iter := tree.Iterator() // root start point
l := []int{14, 15, 20, 21, 30}
for i := 0; iter.Next(); i++ {
if iter.Value().(int) != l[i] {
t.Error("iter Next error", iter.Value(), l[i])
}
}
iter.Next()
if iter.Value().(int) != 30 {
t.Error("Next == false", iter.Value(), iter.Next(), iter.Value())
}
l = []int{21, 20, 15, 14, 7, 7, 6, 5, 4, 3, 2, 1}
for i := 0; iter.Prev(); i++ { // cur is 30 next is 21
if iter.Value().(int) != l[i] {
t.Error(iter.Value())
}
}
if iter.Prev() != false {
t.Error("Prev is error, cur is tail, val = 1 Prev return false")
}
if iter.Value().(int) != 1 { // cur is 1
t.Error("next == false", iter.Value(), iter.Prev(), iter.Value())
}
if iter.Next() != true && iter.Value().(int) != 2 {
t.Error("next to prev is error")
}
}
func TestGetRange(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v, v)
}
// t.Error(tree.debugString())
// t.Error(tree.getArountNode(20))
// t.Error(tree.Values())
result := tree.GetRange(0, 20)
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(-5, -1)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(7, 20)
if spew.Sprint(result) != "[8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(30, 40)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(30, 60)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(40, 40)
if spew.Sprint(result) != "[40]" {
t.Error(result)
}
result = tree.GetRange(50, 60)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(50, 1)
if spew.Sprint(result) != "[40 30 17 13 10 8 6 5 2 1]" {
t.Error(result)
}
result = tree.GetRange(30, 20)
if spew.Sprint(result) != "[30]" {
t.Error(result)
}
}
func TestGetAround(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
tree.Put(v, v)
}
var Result string
Result = spew.Sprint(tree.GetAround(14))
if Result != "[7 14 14]" {
t.Error(tree.Values())
t.Error("14 is root, tree.GetAround(14)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(tree.GetAround(17))
if Result != "[16 17 20]" {
t.Error(tree.Values())
t.Error("tree.GetAround(17)) is error", Result)
t.Error(tree.debugString())
}
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(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 != "[17 <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> 7]" {
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
func TestPutStable(t *testing.T) {
// f, _ := os.OpenFile("./test.log", os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0666)
// log.SetOutput(f)
// 0-1 3 | 2-3 7-8 | 4-7 12-16 | 8-15 20-32 | 16-31 33-58 l := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 18, 19, 20, 21, 22, 30, 41, 41, 41}
// tree := New(compare.Int)
// for i := 0; i < 10; i++ {
// tree.Put(randomdata.Number(0, 100))
// }
// t.Error(tree.debugString())
// t.Error(tree.debugString(), tree.TraversalBreadth(), "\n", "-----------")
}
func TestPutComparatorRandom(t *testing.T) {
for n := 0; n < 300000; n++ {
tree := New(compare.Int)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 10; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + ","
tree.Put(v, v)
godsavl.Put(v, v)
}
}
if tree.String() != godsavl.String() {
t.Error(godsavl.String())
t.Error(tree.debugString())
t.Error(content, n)
break
}
}
}
func TestGet(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
tree.Put(v, v)
}
result := `
│ ┌── 57092
│ ┌── 39016
│ │ └── 36513
│ ┌── 27897
│ │ │ ┌── 23202
│ │ └── 22574
└── 7666
│ ┌── 3055
└── 2383
└── 1562
`
s1 := tree.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 := tree.Get(v)
if !ok {
t.Error("the val not found ", v)
}
}
if v, ok := tree.Get(10000); ok {
t.Error("the val(10000) is not in tree, but is found", v)
}
}
func TestRemoveAll(t *testing.T) {
ALL:
for c := 0; c < 50000; c++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 50; i++ {
v := randomdata.Number(0, 100000)
if _, ok := m[v]; !ok {
m[v] = v
l = append(l, v)
tree.Put(v, v)
gods.Put(v, v)
}
}
for i := 0; i < 50; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(gods.Values())
if s1 != s2 {
t.Error("avl remove error", "avlsize = ", tree.Size())
t.Error(s1)
t.Error(s2)
break ALL
}
}
}
}
func TestRemove(t *testing.T) {
ALL:
for N := 0; N < 500000; N++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 10; i++ {
v := randomdata.Number(0, 100)
if _, ok := m[v]; !ok {
l = append(l, v)
m[v] = v
tree.Put(v, v)
gods.Put(v, v)
}
}
src1 := tree.String()
src2 := gods.String()
for i := 0; i < 10; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
if spew.Sprint(gods.Values()) != spew.Sprint(tree.Values()) && tree.size != 0 {
// if gods.String() != tree.String() && gods.Size() != 0 && tree.size != 0 {
t.Error(src1)
t.Error(src2)
t.Error(tree.debugString())
t.Error(gods.String())
t.Error(l[i])
// t.Error(tree.TraversalDepth(-1))
// t.Error(gods.Values())
break ALL
}
}
}
}
func BenchmarkIterator(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
for _, v := range l {
tree.Put(v, v)
}
b.ResetTimer()
b.StartTimer()
b.N = 0
iter := tree.Iterator()
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
}
func BenchmarkRemove(b *testing.B) {
tree := New(compare.Int)
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 BenchmarkGodsRemove(b *testing.B) {
tree := avltree.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 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) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsRBGet(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsAvlGet(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkPut(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
tree := New(compare.Int)
for _, v := range l {
tree.Put(v, v)
}
}
// b.Log(tree.count)
}
func BenchmarkGodsRBPut(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}
func BenchmarkGodsPut(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}

229
tree/avlkey/iterator.go Normal file
View File

@@ -0,0 +1,229 @@
package avlkey
import (
"474420502.top/eson/structure/lastack"
)
type Iterator struct {
dir int
up *Node
cur *Node
tstack *lastack.Stack
// curnext *Node
}
func initIterator(avltree *Tree) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = avltree.root
return iter
}
func NewIterator(n *Node) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = n
return iter
}
func NewIteratorWithCap(n *Node, cap int) *Iterator {
iter := &Iterator{tstack: lastack.NewWithCap(cap)}
iter.up = n
return iter
}
func (iter *Iterator) SetNode(n *Node) {
iter.up = n
iter.dir = 0
iter.tstack.Clear()
}
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) GetNext(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushNextStack(iter.up)
iter.up = iter.getNextUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getNextUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushNextStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Next() (result bool) {
if iter.dir > -1 {
if iter.dir == 1 && iter.cur != nil {
iter.tstack.Clear()
iter.curPushNextStack(iter.cur)
iter.up = iter.getNextUp(iter.cur)
}
iter.dir = -1
}
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
}
return false
}
func (iter *Iterator) GetPrev(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushPrevStack(iter.up)
iter.up = iter.getPrevUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushPrevStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Prev() (result bool) {
if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev)
if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈
iter.tstack.Clear()
iter.curPushPrevStack(iter.cur) // 把当前cur计算的逆向回朔
iter.up = iter.getPrevUp(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.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
iter.curPushPrevStack(iter.cur)
return true
}
// 如果再次计算的栈为空, 则只能返回false
return false
}
func getRelationship(cur *Node) int {
if cur.parent.children[1] == cur {
return 1
}
return 0
}
func (iter *Iterator) getPrevUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushPrevStack(cur *Node) {
Prev := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值
if Prev != nil {
iter.tstack.Push(Prev)
for Prev.children[1] != nil {
Prev = Prev.children[1]
iter.tstack.Push(Prev) // 入栈 用于回溯
}
}
}
func (iter *Iterator) getNextUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushNextStack(cur *Node) {
next := cur.children[1]
if next != nil {
iter.tstack.Push(next)
for next.children[0] != nil {
next = next.children[0]
iter.tstack.Push(next)
}
}
}

813
tree/avlkeydup/avlkeydup.go Normal file
View File

@@ -0,0 +1,813 @@
package avlkeydup
import (
"474420502.top/eson/structure/compare"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
children [2]*Node
parent *Node
height int
key, value interface{}
}
func (n *Node) String() string {
if n == nil {
return "nil"
}
p := "nil"
if n.parent != nil {
p = spew.Sprint(n.parent.value)
}
return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.height) + ")"
}
type Tree struct {
root *Node
size int
Compare compare.Compare
iter *Iterator
}
func New(Compare compare.Compare) *Tree {
return &Tree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)}
}
func (tree *Tree) String() string {
if tree.size == 0 {
return ""
}
str := "AVLTree\n"
output(tree.root, "", true, &str)
return str
}
func (tree *Tree) Iterator() *Iterator {
return initIterator(tree)
}
func (tree *Tree) Size() int {
return tree.size
}
func (tree *Tree) Remove(key interface{}) (interface{}, bool) {
if n, ok := tree.GetNode(key); ok {
tree.size--
if tree.size == 0 {
tree.root = nil
return n.value, true
}
left := getHeight(n.children[0])
right := getHeight(n.children[1])
if left == -1 && right == -1 {
p := n.parent
p.children[getRelationship(n)] = nil
tree.fixRemoveHeight(p)
return n.value, true
}
var cur *Node
if left > right {
cur = n.children[0]
for cur.children[1] != nil {
cur = cur.children[1]
}
cleft := cur.children[0]
cur.parent.children[getRelationship(cur)] = cleft
if cleft != nil {
cleft.parent = cur.parent
}
} else {
cur = n.children[1]
for cur.children[0] != nil {
cur = cur.children[0]
}
cright := cur.children[1]
cur.parent.children[getRelationship(cur)] = cright
if cright != nil {
cright.parent = cur.parent
}
}
cparent := cur.parent
// 修改为interface 交换
n.value, cur.value = cur.value, n.value
n.key, cur.key = cur.key, n.key
// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
if cparent == n {
tree.fixRemoveHeight(n)
} else {
tree.fixRemoveHeight(cparent)
}
return cur.value, true
}
return nil, false
}
func (tree *Tree) Clear() {
tree.size = 0
tree.root = nil
tree.iter = NewIteratorWithCap(nil, 16)
}
// Values 返回先序遍历的值
func (tree *Tree) Values() []interface{} {
mszie := 0
if tree.root != nil {
mszie = tree.size
}
result := make([]interface{}, 0, mszie)
tree.Traversal(func(k, v interface{}) bool {
result = append(result, v)
return true
}, LDR)
return result
}
func (tree *Tree) GetRange(k1, k2 interface{}) (result []interface{}) {
c := tree.Compare(k2, k1)
switch c {
case 1:
var min, max *Node
resultmin := tree.getArountNode(k1)
resultmax := tree.getArountNode(k2)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if max == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(min)
iter := tree.iter
for iter.Next() {
result = append(result, iter.Value())
if iter.cur == max {
break
}
}
case -1:
var min, max *Node
resultmin := tree.getArountNode(k2)
resultmax := tree.getArountNode(k1)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if min == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(max)
iter := tree.iter
for iter.Prev() {
result = append(result, iter.Value())
if iter.cur == min {
break
}
}
case 0:
if n, ok := tree.GetNode(k1); ok {
return []interface{}{n.value}
}
return []interface{}{}
}
return
}
func (tree *Tree) Get(key interface{}) (interface{}, bool) {
n, ok := tree.GetNode(key)
if ok {
return n.value, true
}
return n, false
}
func (tree *Tree) GetAround(key interface{}) (result [3]interface{}) {
an := tree.getArountNode(key)
for i, n := range an {
if n != nil {
result[i] = n.value
}
}
return
}
func (tree *Tree) getArountNode(key interface{}) (result [3]*Node) {
var last *Node
var lastc int
for n := tree.root; n != nil; {
last = n
c := tree.Compare(key, n.key)
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 Compare only is allowed in -1, 0, 1")
}
}
switch lastc {
case 1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[0] = last
result[2] = tree.iter.GetNext(last, 1)
}
case -1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[2] = last
result[0] = tree.iter.GetPrev(last, 1)
}
case 0:
if result[1] == nil {
return
}
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
}
return
}
func (tree *Tree) GetNode(key interface{}) (*Node, bool) {
for n := tree.root; n != nil; {
switch c := tree.Compare(key, n.key); c {
case -1:
n = n.children[0]
case 1:
n = n.children[1]
case 0:
return n, true
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
return nil, false
}
func (tree *Tree) Put(key, value interface{}) {
if tree.size == 0 {
tree.size++
tree.root = &Node{key: key, value: value}
return
}
for cur, c := tree.root, 0; ; {
c = tree.Compare(key, cur.key)
if c == -1 {
if cur.children[0] == nil {
tree.size++
cur.children[0] = &Node{key: key, value: value}
cur.children[0].parent = cur
if cur.height == 0 {
tree.fixPutHeight(cur)
}
return
}
cur = cur.children[0]
} else if c == 1 {
if cur.children[1] == nil {
tree.size++
cur.children[1] = &Node{key: key, value: value}
cur.children[1].parent = cur
if cur.height == 0 {
tree.fixPutHeight(cur)
}
return
}
cur = cur.children[1]
} else {
cur.key = key
cur.value = value
return
}
}
}
type TraversalMethod int
const (
// L = left R = right D = Value(dest)
_ TraversalMethod = iota
//DLR 先值 然后左递归 右递归 下面同理
DLR
//LDR 先从左边有序访问到右边 从小到大
LDR
// LRD 同理
LRD
// DRL 同理
DRL
// RDL 先从右边有序访问到左边 从大到小
RDL
// RLD 同理
RLD
)
// Traversal 遍历的方法 默认是LDR 从小到大 Compare 为 l < r
func (tree *Tree) Traversal(every func(k, v interface{}) bool, traversalMethod ...interface{}) {
if tree.root == nil {
return
}
method := LDR
if len(traversalMethod) != 0 {
method = traversalMethod[0].(TraversalMethod)
}
switch method {
case DLR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LDR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LRD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
return true
}
traverasl(tree.root)
case DRL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case RDL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
return true
}
traverasl(tree.root)
case RLD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.key, cur.value) {
return false
}
return true
}
traverasl(tree.root)
}
}
func (tree *Tree) lrrotate(cur *Node) {
const l = 1
const r = 0
movparent := cur.children[l]
mov := movparent.children[r]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
mov.key, cur.key = cur.key, mov.key
if mov.children[l] != nil {
movparent.children[r] = mov.children[l]
movparent.children[r].parent = movparent
//movparent.children[r].child = l
} else {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
//mov.children[l].child = l
} else {
mov.children[l] = nil
}
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
}
func (tree *Tree) rlrotate(cur *Node) {
const l = 0
const r = 1
movparent := cur.children[l]
mov := movparent.children[r]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
mov.key, cur.key = cur.key, mov.key
if mov.children[l] != nil {
movparent.children[r] = mov.children[l]
movparent.children[r].parent = movparent
} else {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
}
func (tree *Tree) rrotate(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
mov.key, cur.key = cur.key, mov.key
// 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 {
mov.children[l] = nil
}
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
}
func (tree *Tree) lrotate(cur *Node) {
const l = 1
const r = 0
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
mov.key, cur.key = cur.key, mov.key
// 不可能为nil
mov.children[l].parent = cur
cur.children[l] = mov.children[l]
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
}
func getMaxAndChildrenHeight(cur *Node) (h1, h2, maxh int) {
h1 = getHeight(cur.children[0])
h2 = getHeight(cur.children[1])
if h1 > h2 {
maxh = h1
} else {
maxh = h2
}
return
}
func getMaxChildrenHeight(cur *Node) int {
h1 := getHeight(cur.children[0])
h2 := getHeight(cur.children[1])
if h1 > h2 {
return h1
}
return h2
}
func getHeight(cur *Node) int {
if cur == nil {
return -1
}
return cur.height
}
func (tree *Tree) fixRemoveHeight(cur *Node) {
for {
lefth, rigthh, lrmax := getMaxAndChildrenHeight(cur)
// 判断当前节点是否有变化, 如果没变化的时候, 不需要往上修复
curheight := lrmax + 1
cur.height = curheight
// 计算高度的差值 绝对值大于2的时候需要旋转
diff := lefth - rigthh
if diff < -1 {
r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式
if getHeight(r.children[0]) > getHeight(r.children[1]) {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
if cur.height == curheight {
return
}
}
if cur.parent == nil {
return
}
cur = cur.parent
}
}
func (tree *Tree) fixPutHeight(cur *Node) {
for {
lefth := getHeight(cur.children[0])
rigthh := getHeight(cur.children[1])
// 计算高度的差值 绝对值大于2的时候需要旋转
diff := lefth - rigthh
if diff < -1 {
r := cur.children[1] // 根据左旋转的右边节点的子节点 左右高度选择旋转的方式
if getHeight(r.children[0]) > getHeight(r.children[1]) {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
} else if diff > 1 {
l := cur.children[0]
if getHeight(l.children[1]) > getHeight(l.children[0]) {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
// 选择一个child的最大高度 + 1为 高度
if lefth > rigthh {
cur.height = lefth + 1
} else {
cur.height = rigthh + 1
}
}
if cur.parent == nil || cur.height < cur.parent.height {
return
}
cur = cur.parent
}
}
func output(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
output(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
*str += spew.Sprint(node.value) + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
output(node.children[0], newPrefix, true, str)
}
}
func outputfordebug(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
outputfordebug(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
suffix := "("
parentv := ""
if node.parent == nil {
parentv = "nil"
} else {
parentv = spew.Sprint(node.parent.value)
}
suffix += parentv + "|" + spew.Sprint(node.height) + ")"
*str += spew.Sprint(node.value) + suffix + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
outputfordebug(node.children[0], newPrefix, true, str)
}
}
func (tree *Tree) debugString() string {
if tree.size == 0 {
return ""
}
str := "AVLTree\n"
outputfordebug(tree.root, "", true, &str)
return str
}

View File

@@ -0,0 +1,486 @@
package avlkeydup
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"474420502.top/eson/structure/compare"
"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 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 TestGetRange(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v, v)
}
// t.Error(tree.debugString())
// t.Error(tree.getArountNode(20))
// t.Error(tree.Values())
result := tree.GetRange(0, 20)
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(-5, -1)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(7, 20)
if spew.Sprint(result) != "[8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(30, 40)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(30, 60)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(40, 40)
if spew.Sprint(result) != "[40]" {
t.Error(result)
}
result = tree.GetRange(50, 60)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(50, 1)
if spew.Sprint(result) != "[40 30 17 13 10 8 6 5 2 1]" {
t.Error(result)
}
result = tree.GetRange(30, 20)
if spew.Sprint(result) != "[30]" {
t.Error(result)
}
}
func TestGetAround(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
tree.Put(v, v)
}
var Result string
Result = spew.Sprint(tree.GetAround(14))
if Result != "[7 14 15]" {
t.Error(tree.Values())
t.Error("17 is root, tree.GetAround(14)) is error", Result)
t.Error(tree.debugString())
}
Result = spew.Sprint(tree.GetAround(17))
if Result != "[16 17 20]" {
t.Error(tree.Values())
t.Error("tree.GetAround(17)) is error", Result)
t.Error(tree.debugString())
}
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(tree.GetAround(40))
if Result != "[30 40 50]" {
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 != "[17 <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> 7]" {
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
func TestPutStable(t *testing.T) {
// t.Error(tree.debugString(), tree.TraversalBreadth(), "\n", "-----------")
}
func TestPutComparatorRandom(t *testing.T) {
for n := 0; n < 300000; n++ {
tree := New(compare.Int)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 10; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + ","
tree.Put(v, v)
godsavl.Put(v, v)
}
}
if tree.String() != godsavl.String() {
t.Error(godsavl.String())
t.Error(tree.debugString())
t.Error(content, n)
break
}
}
}
func TestGet(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
tree.Put(v, v)
}
result := `
│ ┌── 57092
│ ┌── 39016
│ │ └── 36513
│ ┌── 27897
│ │ │ ┌── 23202
│ │ └── 22574
└── 7666
│ ┌── 3055
└── 2383
└── 1562
`
s1 := tree.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 := tree.Get(v)
if !ok {
t.Error("the val not found ", v)
}
}
if v, ok := tree.Get(10000); ok {
t.Error("the val(10000) is not in tree, but is found", v)
}
}
func TestRemoveAll(t *testing.T) {
ALL:
for c := 0; c < 5000; c++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 100; i++ {
v := randomdata.Number(0, 100000)
if _, ok := m[v]; !ok {
m[v] = v
l = append(l, v)
tree.Put(v, v)
gods.Put(v, v)
}
}
for i := 0; i < 100; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(gods.Values())
if s1 != s2 {
t.Error("avl remove error", "avlsize = ", tree.Size())
t.Error(s1)
t.Error(s2)
break ALL
}
}
}
}
func TestRemove(t *testing.T) {
ALL:
for N := 0; N < 500000; N++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 10; i++ {
v := randomdata.Number(0, 100)
if _, ok := m[v]; !ok {
l = append(l, v)
m[v] = v
tree.Put(v, v)
gods.Put(v, v)
}
}
src1 := tree.String()
src2 := gods.String()
for i := 0; i < 10; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
if spew.Sprint(gods.Values()) != spew.Sprint(tree.Values()) && tree.size != 0 {
// if gods.String() != tree.String() && gods.Size() != 0 && tree.size != 0 {
t.Error(src1)
t.Error(src2)
t.Error(tree.debugString())
t.Error(gods.String())
t.Error(l[i])
// t.Error(tree.TraversalDepth(-1))
// t.Error(gods.Values())
break ALL
}
}
}
}
func BenchmarkIterator(b *testing.B) {
tree := New(utils.IntComparator)
l := loadTestData()
for _, v := range l {
tree.Put(v, v)
}
b.ResetTimer()
b.StartTimer()
b.N = 0
iter := tree.Iterator()
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
}
func BenchmarkRemove(b *testing.B) {
tree := New(utils.IntComparator)
l := loadTestData()
for _, v := range l {
tree.Put(v, v)
}
ll := tree.Values()
b.N = len(ll)
b.ResetTimer()
b.StartTimer()
for i := 0; i < len(ll); i++ {
tree.Remove(l[i])
}
}
func BenchmarkGodsRemove(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
ll := tree.Values()
b.N = len(ll)
b.ResetTimer()
b.StartTimer()
for i := 0; i < len(ll); 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)
}
ll := tree.Values()
b.N = len(ll)
b.ResetTimer()
b.StartTimer()
for i := 0; i < len(ll); i++ {
tree.Remove(l[i])
}
}
func BenchmarkGet(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsRBGet(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
tree.Get(l[i])
}
}
func BenchmarkGodsAvlGet(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
tree.Get(l[i])
}
}
func BenchmarkPut(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 1000
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
tree := New(compare.Int)
for _, v := range l {
tree.Put(v, v)
}
}
// b.Log(tree.count)
}
func BenchmarkGodsRBPut(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}
func BenchmarkGodsPut(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}

229
tree/avlkeydup/iterator.go Normal file
View File

@@ -0,0 +1,229 @@
package avlkeydup
import (
"474420502.top/eson/structure/lastack"
)
type Iterator struct {
dir int
up *Node
cur *Node
tstack *lastack.Stack
// curnext *Node
}
func initIterator(avltree *Tree) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = avltree.root
return iter
}
func NewIterator(n *Node) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = n
return iter
}
func NewIteratorWithCap(n *Node, cap int) *Iterator {
iter := &Iterator{tstack: lastack.NewWithCap(cap)}
iter.up = n
return iter
}
func (iter *Iterator) SetNode(n *Node) {
iter.up = n
iter.dir = 0
iter.tstack.Clear()
}
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) GetNext(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushNextStack(iter.up)
iter.up = iter.getNextUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getNextUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushNextStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Next() (result bool) {
if iter.dir > -1 {
if iter.dir == 1 && iter.cur != nil {
iter.tstack.Clear()
iter.curPushNextStack(iter.cur)
iter.up = iter.getNextUp(iter.cur)
}
iter.dir = -1
}
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
}
return false
}
func (iter *Iterator) GetPrev(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushPrevStack(iter.up)
iter.up = iter.getPrevUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushPrevStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Prev() (result bool) {
if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev)
if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈
iter.tstack.Clear()
iter.curPushPrevStack(iter.cur) // 把当前cur计算的逆向回朔
iter.up = iter.getPrevUp(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.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
iter.curPushPrevStack(iter.cur)
return true
}
// 如果再次计算的栈为空, 则只能返回false
return false
}
func getRelationship(cur *Node) int {
if cur.parent.children[1] == cur {
return 1
}
return 0
}
func (iter *Iterator) getPrevUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushPrevStack(cur *Node) {
Prev := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值
if Prev != nil {
iter.tstack.Push(Prev)
for Prev.children[1] != nil {
Prev = Prev.children[1]
iter.tstack.Push(Prev) // 入栈 用于回溯
}
}
}
func (iter *Iterator) getNextUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushNextStack(cur *Node) {
next := cur.children[1]
if next != nil {
iter.tstack.Push(next)
for next.children[0] != nil {
next = next.children[0]
iter.tstack.Push(next)
}
}
}

229
tree/vbt/iterator.go Normal file
View File

@@ -0,0 +1,229 @@
package vbt
import (
"474420502.top/eson/structure/lastack"
)
type Iterator struct {
dir int
up *Node
cur *Node
tstack *lastack.Stack
// curnext *Node
}
func initIterator(avltree *Tree) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = avltree.root
return iter
}
func NewIterator(n *Node) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = n
return iter
}
func NewIteratorWithCap(n *Node, cap int) *Iterator {
iter := &Iterator{tstack: lastack.NewWithCap(cap)}
iter.up = n
return iter
}
func (iter *Iterator) SetNode(n *Node) {
iter.up = n
iter.dir = 0
iter.tstack.Clear()
}
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) GetNext(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushNextStack(iter.up)
iter.up = iter.getNextUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getNextUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushNextStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Next() (result bool) {
if iter.dir > -1 {
if iter.dir == 1 && iter.cur != nil {
iter.tstack.Clear()
iter.curPushNextStack(iter.cur)
iter.up = iter.getNextUp(iter.cur)
}
iter.dir = -1
}
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
}
return false
}
func (iter *Iterator) GetPrev(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushPrevStack(iter.up)
iter.up = iter.getPrevUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushPrevStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Prev() (result bool) {
if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev)
if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈
iter.tstack.Clear()
iter.curPushPrevStack(iter.cur) // 把当前cur计算的逆向回朔
iter.up = iter.getPrevUp(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.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
iter.curPushPrevStack(iter.cur)
return true
}
// 如果再次计算的栈为空, 则只能返回false
return false
}
func getRelationship(cur *Node) int {
if cur.parent.children[1] == cur {
return 1
}
return 0
}
func (iter *Iterator) getPrevUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushPrevStack(cur *Node) {
Prev := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值
if Prev != nil {
iter.tstack.Push(Prev)
for Prev.children[1] != nil {
Prev = Prev.children[1]
iter.tstack.Push(Prev) // 入栈 用于回溯
}
}
}
func (iter *Iterator) getNextUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushNextStack(cur *Node) {
next := cur.children[1]
if next != nil {
iter.tstack.Push(next)
for next.children[0] != nil {
next = next.children[0]
iter.tstack.Push(next)
}
}
}

986
tree/vbt/vbt.go Normal file
View File

@@ -0,0 +1,986 @@
package vbt
import (
"474420502.top/eson/structure/compare"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
children [2]*Node
parent *Node
size int
value interface{}
}
func (n *Node) String() string {
if n == nil {
return "nil"
}
p := "nil"
if n.parent != nil {
p = spew.Sprint(n.parent.value)
}
return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.size) + ")"
}
type Tree struct {
root *Node
Compare compare.Compare
iter *Iterator
}
func New(Compare compare.Compare) *Tree {
return &Tree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)}
}
func (tree *Tree) String() string {
str := "AVLTree\n"
if tree.root == nil {
return str + "nil"
}
output(tree.root, "", true, &str)
return str
}
func (tree *Tree) Iterator() *Iterator {
return initIterator(tree)
}
func (tree *Tree) Size() int {
if tree.root == nil {
return 0
}
return tree.root.size
}
func (tree *Tree) indexNode(idx int) *Node {
cur := tree.root
if idx >= 0 {
for cur != nil {
ls := getSize(cur.children[0])
if idx == ls {
return cur
} else if idx < ls {
cur = cur.children[0]
} else {
idx = idx - ls - 1
cur = cur.children[1]
}
}
} else {
idx = -idx - 1
for cur != nil {
rs := getSize(cur.children[1])
if idx == rs {
return cur
} else if idx < rs {
cur = cur.children[1]
} else {
idx = idx - rs - 1
cur = cur.children[0]
}
}
}
return nil
}
func (tree *Tree) Index(idx int) (interface{}, bool) {
n := tree.indexNode(idx)
if n != nil {
return n.value, true
}
return nil, false
}
func (tree *Tree) IndexRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1
if idx1^idx2 < 0 {
if idx1 < 0 {
idx1 = tree.root.size + idx1 - 1
} else {
idx2 = tree.root.size + idx2 - 1
}
}
if idx1 > idx2 {
ok = true
if idx1 >= tree.root.size {
idx1 = tree.root.size - 1
ok = false
}
n := tree.indexNode(idx1)
tree.iter.SetNode(n)
iter := tree.iter
result = make([]interface{}, 0, idx1-idx2)
for i := idx2; i <= idx1; i++ {
if iter.Prev() {
result = append(result, iter.Value())
} else {
ok = false
return
}
}
return
} else {
ok = true
if idx2 >= tree.root.size {
idx2 = tree.root.size - 1
ok = false
}
if n := tree.indexNode(idx1); n != nil {
tree.iter.SetNode(n)
iter := tree.iter
result = make([]interface{}, 0, idx2-idx1)
for i := idx1; i <= idx2; i++ {
if iter.Next() {
result = append(result, iter.Value())
} else {
ok = false
return
}
}
return
}
}
return nil, false
}
func (tree *Tree) RemoveIndex(idx int) (interface{}, bool) {
n := tree.indexNode(idx)
if n != nil {
tree.removeNode(n)
return n.value, true
}
return nil, false
}
func (tree *Tree) removeNode(n *Node) {
if tree.root.size == 1 {
tree.root = nil
// return n
return
}
ls, rs := getChildrenSize(n)
if ls == 0 && rs == 0 {
p := n.parent
p.children[getRelationship(n)] = nil
tree.fixSizeWithRemove(p)
// return n
return
}
var cur *Node
if ls > rs {
cur = n.children[0]
for cur.children[1] != nil {
cur = cur.children[1]
}
cleft := cur.children[0]
cur.parent.children[getRelationship(cur)] = cleft
if cleft != nil {
cleft.parent = cur.parent
}
} else {
cur = n.children[1]
for cur.children[0] != nil {
cur = cur.children[0]
}
cright := cur.children[1]
cur.parent.children[getRelationship(cur)] = cright
if cright != nil {
cright.parent = cur.parent
}
}
cparent := cur.parent
// 修改为interface 交换
n.value, cur.value = cur.value, n.value
// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
if cparent == n {
tree.fixSizeWithRemove(n)
} else {
tree.fixSizeWithRemove(cparent)
}
// return cur
return
}
func (tree *Tree) Remove(key interface{}) (interface{}, bool) {
if n, ok := tree.GetNode(key); ok {
tree.removeNode(n)
return n.value, true
}
// return nil
return nil, false
}
// Values 返回先序遍历的值
func (tree *Tree) Values() []interface{} {
mszie := 0
if tree.root != nil {
mszie = tree.root.size
}
result := make([]interface{}, 0, mszie)
tree.Traversal(func(v interface{}) bool {
result = append(result, v)
return true
}, LDR)
return result
}
func (tree *Tree) GetRange(k1, k2 interface{}) (result []interface{}) {
c := tree.Compare(k2, k1)
switch c {
case 1:
var min, max *Node
resultmin := tree.getArountNode(k1)
resultmax := tree.getArountNode(k2)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if max == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(min)
iter := tree.iter
for iter.Next() {
result = append(result, iter.Value())
if iter.cur == max {
break
}
}
case -1:
var min, max *Node
resultmin := tree.getArountNode(k2)
resultmax := tree.getArountNode(k1)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if min == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(max)
iter := tree.iter
for iter.Prev() {
result = append(result, iter.Value())
if iter.cur == min {
break
}
}
case 0:
if n, ok := tree.GetNode(k1); ok {
return []interface{}{n.value}
}
return []interface{}{}
}
return
}
func (tree *Tree) Get(key interface{}) (interface{}, bool) {
n, ok := tree.GetNode(key)
if ok {
return n.value, true
}
return n, false
}
func (tree *Tree) GetAround(key interface{}) (result [3]interface{}) {
an := tree.getArountNode(key)
for i, n := range an {
if n != nil {
result[i] = n.value
}
}
return
}
func (tree *Tree) getArountNode(key interface{}) (result [3]*Node) {
var last *Node
var lastc int
for n := tree.root; n != nil; {
last = n
c := tree.Compare(key, n.value)
switch c {
case -1:
n = n.children[0]
lastc = c
case 1:
n = n.children[1]
lastc = c
case 0:
tree.iter.SetNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.value, n.value) == 0 {
n = iter.cur
} else {
break
}
}
result[1] = n
n = nil
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
switch lastc {
case 1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[0] = last
result[2] = tree.iter.GetNext(last, 1)
}
case -1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[2] = last
result[0] = tree.iter.GetPrev(last, 1)
}
case 0:
if result[1] == nil {
return
}
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
}
return
}
func (tree *Tree) GetNode(value interface{}) (*Node, bool) {
for n := tree.root; n != nil; {
switch c := tree.Compare(value, n.value); c {
case -1:
n = n.children[0]
case 1:
n = n.children[1]
case 0:
tree.iter.SetNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.value, n.value) == 0 {
n = iter.cur
} else {
break
}
}
return n, true
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
return nil, false
}
func (tree *Tree) Put(key interface{}) {
node := &Node{value: key, size: 1}
if tree.root == nil {
tree.root = node
return
}
for cur := tree.root; ; {
if cur.size > 8 {
factor := cur.size / 10 // or factor = 1
ls, rs := cur.children[0].size, cur.children[1].size
if rs >= ls*2+factor || ls >= rs*2+factor {
tree.fixSize(cur, ls, rs)
}
}
cur.size++
c := tree.Compare(key, cur.value)
if c < 0 {
if cur.children[0] == nil {
cur.children[0] = node
node.parent = cur
if cur.parent != nil && cur.parent.size == 3 {
if cur.parent.children[0] == nil {
tree.lrrotate3(cur.parent)
} else {
tree.rrotate3(cur.parent)
}
}
return
}
cur = cur.children[0]
} else {
if cur.children[1] == nil {
cur.children[1] = node
node.parent = cur
if cur.parent != nil && cur.parent.size == 3 {
if cur.parent.children[1] == nil {
tree.rlrotate3(cur.parent)
} else {
tree.lrotate3(cur.parent)
}
}
return
}
cur = cur.children[1]
}
}
}
type TraversalMethod int
const (
// L = left R = right D = Value(dest)
_ TraversalMethod = iota
//DLR 先值 然后左递归 右递归 下面同理
DLR
//LDR 先从左边有序访问到右边 从小到大
LDR
// LRD 同理
LRD
// DRL 同理
DRL
// RDL 先从右边有序访问到左边 从大到小
RDL
// RLD 同理
RLD
)
// Traversal 遍历的方法 默认是LDR 从小到大 Compare 为 l < r
func (tree *Tree) Traversal(every func(v interface{}) bool, traversalMethod ...interface{}) {
if tree.root == nil {
return
}
method := LDR
if len(traversalMethod) != 0 {
method = traversalMethod[0].(TraversalMethod)
}
switch method {
case DLR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LDR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LRD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
case DRL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case RDL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
return true
}
traverasl(tree.root)
case RLD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
}
}
func (tree *Tree) lrrotate3(cur *Node) {
const l = 1
const r = 0
mov := cur.children[l].children[r]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
cur.children[r] = mov
mov.parent = cur
cur.children[l].children[r] = nil
cur.children[r] = mov
mov.parent = cur
// cur.size = 3
// cur.children[r].size = 1
cur.children[l].size = 1
}
func (tree *Tree) lrrotate(cur *Node) {
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 {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
//mov.children[l].child = l
} else {
mov.children[l] = nil
}
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
movparent.size = getChildrenSumSize(movparent) + 1
mov.size = getChildrenSumSize(mov) + 1
cur.size = getChildrenSumSize(cur) + 1
}
func (tree *Tree) rlrotate3(cur *Node) {
const l = 0
const r = 1
mov := cur.children[l].children[r]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
cur.children[r] = mov
mov.parent = cur
cur.children[l].children[r] = nil
cur.children[r] = mov
mov.parent = cur
// cur.size = 3
// cur.children[r].size = 1
cur.children[l].size = 1
}
func (tree *Tree) rlrotate(cur *Node) {
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 {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
movparent.size = getChildrenSumSize(movparent) + 1
mov.size = getChildrenSumSize(mov) + 1
cur.size = getChildrenSumSize(cur) + 1
}
func (tree *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
cur.children[l] = mov.children[l]
cur.children[l].parent = cur
mov.children[l] = nil
mov.size = 1
}
func (tree *Tree) rrotate(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
// 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 {
mov.children[l] = nil
}
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.size = getChildrenSumSize(mov) + 1
cur.size = getChildrenSumSize(cur) + 1
}
func (tree *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
cur.children[l] = mov.children[l]
cur.children[l].parent = cur
mov.children[l] = nil
mov.size = 1
}
func (tree *Tree) lrotate(cur *Node) {
const l = 1
const r = 0
// 1 right 0 left
mov := cur.children[l]
mov.value, cur.value = cur.value, mov.value //交换值达到, 相对位移
// 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 {
mov.children[l] = nil
}
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.size = getChildrenSumSize(mov) + 1
cur.size = getChildrenSumSize(cur) + 1
}
func getChildrenSumSize(cur *Node) int {
return getSize(cur.children[0]) + getSize(cur.children[1])
}
func getChildrenSize(cur *Node) (int, int) {
return getSize(cur.children[0]), getSize(cur.children[1])
}
func getSize(cur *Node) int {
if cur == nil {
return 0
}
return cur.size
}
func (tree *Tree) fixSizeWithRemove(cur *Node) {
for cur != nil {
cur.size--
if cur.size > 8 {
factor := cur.size / 10 // or factor = 1
ls, rs := getChildrenSize(cur)
if rs >= ls*2+factor || ls >= rs*2+factor {
tree.fixSize(cur, ls, rs)
}
} else if cur.size == 3 {
if cur.children[0] == nil {
if cur.children[1].children[0] == nil {
tree.lrotate3(cur)
} else {
tree.lrrotate3(cur)
}
} else if cur.children[1] == nil {
if cur.children[0].children[1] == nil {
tree.rrotate3(cur)
} else {
tree.rlrotate3(cur)
}
}
}
cur = cur.parent
}
}
func (tree *Tree) fixSize(cur *Node, ls, rs int) {
if ls > rs {
llsize, lrsize := getChildrenSize(cur.children[0])
if lrsize > llsize {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
rlsize, rrsize := getChildrenSize(cur.children[1])
if rlsize > rrsize {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
}
}
func output(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
output(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
*str += spew.Sprint(node.value) + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
output(node.children[0], newPrefix, true, str)
}
}
func outputfordebug(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
outputfordebug(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
suffix := "("
parentv := ""
if node.parent == nil {
parentv = "nil"
} else {
parentv = spew.Sprint(node.parent.value)
}
suffix += parentv + "|" + spew.Sprint(node.size) + ")"
*str += spew.Sprint(node.value) + suffix + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
outputfordebug(node.children[0], newPrefix, true, str)
}
}
func (tree *Tree) debugString() string {
str := "AVLTree\n"
if tree.root == nil {
return str + "nil"
}
outputfordebug(tree.root, "", true, &str)
return str
}

656
tree/vbt/vbt_test.go Normal file
View File

@@ -0,0 +1,656 @@
package vbt
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"474420502.top/eson/structure/compare"
"github.com/huandu/skiplist"
"github.com/Pallinder/go-randomdata"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/avltree"
"github.com/emirpasic/gods/trees/redblacktree"
)
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 TestIndexRange(t *testing.T) {
tree := New(compare.Int)
l := []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15}
for _, v := range l {
tree.Put(v)
}
// [3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50]
// t.Error(tree.Values(), tree.Size())
var result string
result = spew.Sprint(tree.IndexRange(0, 5))
if result != "[3 7 14 14 14 15] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(2, 5))
if result != "[14 14 14 15] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(10, 100))
if result != "[30 40 40 40 40 50] false" {
t.Error(result)
}
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.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.IndexRange(5, 1)) // size = 16, index max = 15
if result != "[15 14 14 14 7] true" {
t.Error(result)
}
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.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.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.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) {
tree := New(compare.Int)
for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
tree.Put(v)
}
var Result string
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(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(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 != "[17 <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> 7]" {
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
func TestPutComparatorRandom(t *testing.T) {
for n := 0; n < 100000; n++ {
tree := New(compare.Int)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 20; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + ","
tree.Put(v)
godsavl.Put(v, v)
}
}
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(godsavl.Values())
if s1 != s2 {
t.Error(godsavl.String())
t.Error(tree.debugString())
t.Error(content, n)
break
}
}
}
func TestGet(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
tree.Put(v)
}
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
v, ok := tree.Get(v)
if !ok {
t.Error("the val not found ", v)
}
}
if v, ok := tree.Get(10000); ok {
t.Error("the val(1000) is not in tree, but is found", v)
}
}
func TestGetRange(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v)
}
// t.Error(tree.debugString())
// t.Error(tree.getArountNode(20))
// t.Error(tree.Values())
result := tree.GetRange(0, 20)
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(-5, -1)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(7, 20)
if spew.Sprint(result) != "[8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(30, 40)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(30, 60)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(40, 40)
if spew.Sprint(result) != "[40]" {
t.Error(result)
}
result = tree.GetRange(50, 60)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(50, 1)
if spew.Sprint(result) != "[40 30 17 13 10 8 6 5 2 1]" {
t.Error(result)
}
result = tree.GetRange(30, 20)
if spew.Sprint(result) != "[30]" {
t.Error(result)
}
}
func TestTravalsal(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v)
}
i := 0
var result []interface{}
tree.Traversal(func(v interface{}) bool {
result = append(result, v)
i++
if i >= 10 {
return false
}
return true
})
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17 30 40]" {
t.Error(result)
}
}
func TestRemoveAll(t *testing.T) {
ALL:
for c := 0; c < 10000; c++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 100; i++ {
v := randomdata.Number(0, 100000)
if _, ok := m[v]; !ok {
m[v] = v
l = append(l, v)
tree.Put(v)
gods.Put(v, v)
}
}
for i := 0; i < 100; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(gods.Values())
if s1 != s2 {
t.Error("avl remove error", "avlsize = ", tree.Size())
t.Error(tree.root, i, l[i])
t.Error(s1)
t.Error(s2)
break ALL
}
}
}
}
func TestRemove(t *testing.T) {
ALL:
for N := 0; N < 5000; N++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 20; i++ {
v := randomdata.Number(0, 100)
if _, ok := m[v]; !ok {
l = append(l, v)
m[v] = v
tree.Put(v)
gods.Put(v, v)
}
}
src1 := tree.String()
src2 := gods.String()
for i := 0; i < 20; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
if tree.root != nil && spew.Sprint(gods.Values()) != spew.Sprint(tree.Values()) {
t.Error(src1)
t.Error(src2)
t.Error(tree.debugString())
t.Error(gods.String())
t.Error(l[i])
break ALL
}
}
}
}
func BenchmarkSkipRemove(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()
for _, v := range l {
sl.Remove(v)
}
}
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) {
}
func BenchmarkIndexRange(b *testing.B) {
tree := New(compare.Int)
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.IndexRange(i, i+49)
}
}
}
func BenchmarkSkipListSet(b *testing.B) {
l := loadTestData()
execCount := 1
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
sl := skiplist.New(skiplist.Int)
for _, v := range l {
sl.Set(v, v)
}
}
}
func BenchmarkIterator(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v)
}
b.ResetTimer()
b.StartTimer()
iter := tree.Iterator()
b.N = 0
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
for iter.Next() {
b.N++
}
b.Log(b.N, len(l))
}
func BenchmarkRemove(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v)
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < len(l); i++ {
tree.Remove(l[i])
}
}
func BenchmarkGodsRemove(b *testing.B) {
tree := avltree.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 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) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i])
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsRBGet(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], i)
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsAvlGet(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], i)
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkPut(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 50
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
tree := New(compare.Int)
for _, v := range l {
tree.Put(v)
}
}
}
func TestPutStable(t *testing.T) {
}
func BenchmarkIndex(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i])
}
b.ResetTimer()
b.StartTimer()
for i := 0; i < b.N; i++ {
tree.Index(i)
}
}
func BenchmarkGodsRBPut(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}
func BenchmarkGodsPut(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}

229
tree/vbtkey/iterator.go Normal file
View File

@@ -0,0 +1,229 @@
package vbtkey
import (
"474420502.top/eson/structure/lastack"
)
type Iterator struct {
dir int
up *Node
cur *Node
tstack *lastack.Stack
// curnext *Node
}
func initIterator(avltree *Tree) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = avltree.root
return iter
}
func NewIterator(n *Node) *Iterator {
iter := &Iterator{tstack: lastack.New()}
iter.up = n
return iter
}
func NewIteratorWithCap(n *Node, cap int) *Iterator {
iter := &Iterator{tstack: lastack.NewWithCap(cap)}
iter.up = n
return iter
}
func (iter *Iterator) SetNode(n *Node) {
iter.up = n
iter.dir = 0
iter.tstack.Clear()
}
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) GetNext(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushNextStack(iter.up)
iter.up = iter.getNextUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getNextUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushNextStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Next() (result bool) {
if iter.dir > -1 {
if iter.dir == 1 && iter.cur != nil {
iter.tstack.Clear()
iter.curPushNextStack(iter.cur)
iter.up = iter.getNextUp(iter.cur)
}
iter.dir = -1
}
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
}
return false
}
func (iter *Iterator) GetPrev(cur *Node, idx int) *Node {
// iter := NewIterator(cur)
iter.SetNode(cur)
iter.curPushPrevStack(iter.up)
iter.up = iter.getPrevUp(iter.up)
for i := 0; i < idx; i++ {
if iter.tstack.Size() == 0 {
if iter.up == nil {
return nil
}
iter.tstack.Push(iter.up)
iter.up = iter.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
if i == idx-1 {
return iter.cur
}
iter.curPushPrevStack(iter.cur)
} else {
return nil
}
}
return cur
}
func (iter *Iterator) Prev() (result bool) {
if iter.dir < 1 { // 非 1(next 方向定义 -1 为 prev)
if iter.dir == -1 && iter.cur != nil { // 如果上次为prev方向, 则清空辅助计算的栈
iter.tstack.Clear()
iter.curPushPrevStack(iter.cur) // 把当前cur计算的逆向回朔
iter.up = iter.getPrevUp(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.getPrevUp(iter.up)
}
if v, ok := iter.tstack.Pop(); ok {
iter.cur = v.(*Node)
iter.curPushPrevStack(iter.cur)
return true
}
// 如果再次计算的栈为空, 则只能返回false
return false
}
func getRelationship(cur *Node) int {
if cur.parent.children[1] == cur {
return 1
}
return 0
}
func (iter *Iterator) getPrevUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 1 { // next 在 降序 小值. 如果child在右边, parent 比 child 小, parent才有效, 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushPrevStack(cur *Node) {
Prev := cur.children[0] // 当前的左然后向右找, 找到最大, 就是最接近cur 并且小于cur的值
if Prev != nil {
iter.tstack.Push(Prev)
for Prev.children[1] != nil {
Prev = Prev.children[1]
iter.tstack.Push(Prev) // 入栈 用于回溯
}
}
}
func (iter *Iterator) getNextUp(cur *Node) *Node {
for cur.parent != nil {
if getRelationship(cur) == 0 { // Prev 在 降序 大值. 如果child在左边, parent 比 child 大, parent才有效 , 符合降序
return cur.parent
}
cur = cur.parent
}
return nil
}
func (iter *Iterator) curPushNextStack(cur *Node) {
next := cur.children[1]
if next != nil {
iter.tstack.Push(next)
for next.children[0] != nil {
next = next.children[0]
iter.tstack.Push(next)
}
}
}

995
tree/vbtkey/vbtkey.go Normal file
View File

@@ -0,0 +1,995 @@
package vbtkey
import (
"474420502.top/eson/structure/compare"
"github.com/davecgh/go-spew/spew"
)
type Node struct {
children [2]*Node
parent *Node
size int
key interface{}
value interface{}
}
func (n *Node) String() string {
if n == nil {
return "nil"
}
p := "nil"
if n.parent != nil {
p = spew.Sprint(n.parent.value)
}
return spew.Sprint(n.value) + "(" + p + "|" + spew.Sprint(n.size) + ")"
}
type Tree struct {
root *Node
Compare compare.Compare
iter *Iterator
}
func New(Compare compare.Compare) *Tree {
return &Tree{Compare: Compare, iter: NewIteratorWithCap(nil, 16)}
}
func (tree *Tree) String() string {
str := "AVLTree\n"
if tree.root == nil {
return str + "nil"
}
output(tree.root, "", true, &str)
return str
}
func (tree *Tree) Iterator() *Iterator {
return initIterator(tree)
}
func (tree *Tree) Size() int {
if tree.root == nil {
return 0
}
return tree.root.size
}
func (tree *Tree) indexNode(idx int) *Node {
cur := tree.root
if idx >= 0 {
for cur != nil {
ls := getSize(cur.children[0])
if idx == ls {
return cur
} else if idx < ls {
cur = cur.children[0]
} else {
idx = idx - ls - 1
cur = cur.children[1]
}
}
} else {
idx = -idx - 1
for cur != nil {
rs := getSize(cur.children[1])
if idx == rs {
return cur
} else if idx < rs {
cur = cur.children[1]
} else {
idx = idx - rs - 1
cur = cur.children[0]
}
}
}
return nil
}
func (tree *Tree) Index(idx int) (interface{}, bool) {
n := tree.indexNode(idx)
if n != nil {
return n.value, true
}
return nil, false
}
func (tree *Tree) IndexRange(idx1, idx2 int) (result []interface{}, ok bool) { // 0 -1
if idx1^idx2 < 0 {
if idx1 < 0 {
idx1 = tree.root.size + idx1 - 1
} else {
idx2 = tree.root.size + idx2 - 1
}
}
if idx1 > idx2 {
ok = true
if idx1 >= tree.root.size {
idx1 = tree.root.size - 1
ok = false
}
n := tree.indexNode(idx1)
tree.iter.SetNode(n)
iter := tree.iter
result = make([]interface{}, 0, idx1-idx2)
for i := idx2; i <= idx1; i++ {
if iter.Prev() {
result = append(result, iter.Value())
} else {
ok = false
return
}
}
return
} else {
ok = true
if idx2 >= tree.root.size {
idx2 = tree.root.size - 1
ok = false
}
if n := tree.indexNode(idx1); n != nil {
tree.iter.SetNode(n)
iter := tree.iter
result = make([]interface{}, 0, idx2-idx1)
for i := idx1; i <= idx2; i++ {
if iter.Next() {
result = append(result, iter.Value())
} else {
ok = false
return
}
}
return
}
}
return nil, false
}
func (tree *Tree) RemoveIndex(idx int) (interface{}, bool) {
n := tree.indexNode(idx)
if n != nil {
tree.removeNode(n)
return n.value, true
}
return nil, false
}
func (tree *Tree) removeNode(n *Node) {
if tree.root.size == 1 {
tree.root = nil
// return n
return
}
ls, rs := getChildrenSize(n)
if ls == 0 && rs == 0 {
p := n.parent
p.children[getRelationship(n)] = nil
tree.fixSizeWithRemove(p)
// return n
return
}
var cur *Node
if ls > rs {
cur = n.children[0]
for cur.children[1] != nil {
cur = cur.children[1]
}
cleft := cur.children[0]
cur.parent.children[getRelationship(cur)] = cleft
if cleft != nil {
cleft.parent = cur.parent
}
} else {
cur = n.children[1]
for cur.children[0] != nil {
cur = cur.children[0]
}
cright := cur.children[1]
cur.parent.children[getRelationship(cur)] = cright
if cright != nil {
cright.parent = cur.parent
}
}
cparent := cur.parent
// 修改为interface 交换
n.key, n.value, cur.key, cur.value = cur.key, cur.value, n.key, n.value
// 考虑到刚好替换的节点是 被替换节点的孩子节点的时候, 从自身修复高度
if cparent == n {
tree.fixSizeWithRemove(n)
} else {
tree.fixSizeWithRemove(cparent)
}
// return cur
return
}
func (tree *Tree) Remove(key interface{}) (interface{}, bool) {
if n, ok := tree.GetNode(key); ok {
tree.removeNode(n)
return n.value, true
}
// return nil
return nil, false
}
// Values 返回先序遍历的值
func (tree *Tree) Values() []interface{} {
mszie := 0
if tree.root != nil {
mszie = tree.root.size
}
result := make([]interface{}, 0, mszie)
tree.Traversal(func(v interface{}) bool {
result = append(result, v)
return true
}, LDR)
return result
}
func (tree *Tree) GetRange(k1, k2 interface{}) (result []interface{}) {
c := tree.Compare(k2, k1)
switch c {
case 1:
var min, max *Node
resultmin := tree.getArountNode(k1)
resultmax := tree.getArountNode(k2)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if max == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(min)
iter := tree.iter
for iter.Next() {
result = append(result, iter.Value())
if iter.cur == max {
break
}
}
case -1:
var min, max *Node
resultmin := tree.getArountNode(k2)
resultmax := tree.getArountNode(k1)
for i := 1; i < 3 && min == nil; i++ {
min = resultmin[i]
}
for i := 1; i > -1 && max == nil; i-- {
max = resultmax[i]
}
if min == nil {
return []interface{}{}
}
result = make([]interface{}, 0, 16)
tree.iter.SetNode(max)
iter := tree.iter
for iter.Prev() {
result = append(result, iter.Value())
if iter.cur == min {
break
}
}
case 0:
if n, ok := tree.GetNode(k1); ok {
return []interface{}{n.value}
}
return []interface{}{}
}
return
}
func (tree *Tree) Get(key interface{}) (interface{}, bool) {
n, ok := tree.GetNode(key)
if ok {
return n.value, true
}
return n, false
}
func (tree *Tree) GetAround(key interface{}) (result [3]interface{}) {
an := tree.getArountNode(key)
for i, n := range an {
if n != nil {
result[i] = n.value
}
}
return
}
func (tree *Tree) getArountNode(key interface{}) (result [3]*Node) {
var last *Node
var lastc int
for n := tree.root; n != nil; {
last = n
c := tree.Compare(key, n.value)
switch c {
case -1:
n = n.children[0]
lastc = c
case 1:
n = n.children[1]
lastc = c
case 0:
tree.iter.SetNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.value, n.value) == 0 {
n = iter.cur
} else {
break
}
}
result[1] = n
n = nil
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
switch lastc {
case 1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[0] = last
result[2] = tree.iter.GetNext(last, 1)
}
case -1:
if result[1] != nil {
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
} else {
result[2] = last
result[0] = tree.iter.GetPrev(last, 1)
}
case 0:
if result[1] == nil {
return
}
result[0] = tree.iter.GetPrev(result[1], 1)
result[2] = tree.iter.GetNext(result[1], 1)
}
return
}
func (tree *Tree) GetNode(key interface{}) (*Node, bool) {
for n := tree.root; n != nil; {
switch c := tree.Compare(key, n.key); c {
case -1:
n = n.children[0]
case 1:
n = n.children[1]
case 0:
tree.iter.SetNode(n)
iter := tree.iter
iter.Prev()
for iter.Prev() {
if tree.Compare(iter.cur.key, n.key) == 0 {
n = iter.cur
} else {
break
}
}
return n, true
default:
panic("Get Compare only is allowed in -1, 0, 1")
}
}
return nil, false
}
func (tree *Tree) Put(key, value interface{}) {
node := &Node{key: key, value: value, size: 1}
if tree.root == nil {
tree.root = node
return
}
for cur := tree.root; ; {
if cur.size > 8 {
factor := cur.size / 10 // or factor = 1
ls, rs := cur.children[0].size, cur.children[1].size
if rs >= ls*2+factor || ls >= rs*2+factor {
tree.fixSize(cur, ls, rs)
}
}
cur.size++
c := tree.Compare(key, cur.key)
if c < 0 {
if cur.children[0] == nil {
cur.children[0] = node
node.parent = cur
if cur.parent != nil && cur.parent.size == 3 {
if cur.parent.children[0] == nil {
tree.lrrotate3(cur.parent)
} else {
tree.rrotate3(cur.parent)
}
}
return
}
cur = cur.children[0]
} else {
if cur.children[1] == nil {
cur.children[1] = node
node.parent = cur
if cur.parent != nil && cur.parent.size == 3 {
if cur.parent.children[1] == nil {
tree.rlrotate3(cur.parent)
} else {
tree.lrotate3(cur.parent)
}
}
return
}
cur = cur.children[1]
}
}
}
type TraversalMethod int
const (
// L = left R = right D = Value(dest)
_ TraversalMethod = iota
//DLR 先值 然后左递归 右递归 下面同理
DLR
//LDR 先从左边有序访问到右边 从小到大
LDR
// LRD 同理
LRD
// DRL 同理
DRL
// RDL 先从右边有序访问到左边 从大到小
RDL
// RLD 同理
RLD
)
// Traversal 遍历的方法 默认是LDR 从小到大 comparator 为 l < r
func (tree *Tree) Traversal(every func(v interface{}) bool, traversalMethod ...interface{}) {
if tree.root == nil {
return
}
method := LDR
if len(traversalMethod) != 0 {
method = traversalMethod[0].(TraversalMethod)
}
switch method {
case DLR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LDR:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case LRD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
case DRL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !traverasl(cur.children[1]) {
return false
}
return true
}
traverasl(tree.root)
case RDL:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !every(cur.value) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
return true
}
traverasl(tree.root)
case RLD:
var traverasl func(cur *Node) bool
traverasl = func(cur *Node) bool {
if cur == nil {
return true
}
if !traverasl(cur.children[1]) {
return false
}
if !traverasl(cur.children[0]) {
return false
}
if !every(cur.value) {
return false
}
return true
}
traverasl(tree.root)
}
}
func (tree *Tree) lrrotate3(cur *Node) {
const l = 1
const r = 0
movparent := cur.children[l]
mov := movparent.children[r]
mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, 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 (tree *Tree) lrrotate(cur *Node) {
const l = 1
const r = 0
movparent := cur.children[l]
mov := movparent.children[r]
mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, mov.value //交换值达到, 相对位移
if mov.children[l] != nil {
movparent.children[r] = mov.children[l]
movparent.children[r].parent = movparent
//movparent.children[r].child = l
} else {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
//mov.children[l].child = l
} else {
mov.children[l] = nil
}
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
movparent.size = getChildrenSumSize(movparent) + 1
mov.size = getChildrenSumSize(mov) + 1
cur.size = getChildrenSumSize(cur) + 1
}
func (tree *Tree) rlrotate3(cur *Node) {
const l = 0
const r = 1
movparent := cur.children[l]
mov := movparent.children[r]
mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, 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 (tree *Tree) rlrotate(cur *Node) {
const l = 0
const r = 1
movparent := cur.children[l]
mov := movparent.children[r]
mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, mov.value //交换值达到, 相对位移
if mov.children[l] != nil {
movparent.children[r] = mov.children[l]
movparent.children[r].parent = movparent
} else {
movparent.children[r] = nil
}
if mov.children[r] != nil {
mov.children[l] = mov.children[r]
} else {
mov.children[l] = nil
}
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
movparent.size = getChildrenSumSize(movparent) + 1
mov.size = getChildrenSumSize(mov) + 1
cur.size = getChildrenSumSize(cur) + 1
}
func (tree *Tree) rrotate3(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, mov.value //交换值达到, 相对位移
cur.children[r] = mov
cur.children[l] = mov.children[l]
cur.children[l].parent = cur
mov.children[l] = nil
mov.size = 1
}
func (tree *Tree) rrotate(cur *Node) {
const l = 0
const r = 1
// 1 right 0 left
mov := cur.children[l]
mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, mov.value //交换值达到, 相对位移
// 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 {
mov.children[l] = nil
}
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.size = getChildrenSumSize(mov) + 1
cur.size = getChildrenSumSize(cur) + 1
}
func (tree *Tree) lrotate3(cur *Node) {
const l = 1
const r = 0
// 1 right 0 left
mov := cur.children[l]
mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, mov.value //交换值达到, 相对位移
cur.children[r] = mov
cur.children[l] = mov.children[l]
cur.children[l].parent = cur
mov.children[l] = nil
mov.size = 1
}
func (tree *Tree) lrotate(cur *Node) {
const l = 1
const r = 0
// 1 right 0 left
mov := cur.children[l]
mov.key, mov.value, cur.key, cur.value = cur.key, cur.value, mov.key, mov.value //交换值达到, 相对位移
// 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 {
mov.children[l] = nil
}
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.size = getChildrenSumSize(mov) + 1
cur.size = getChildrenSumSize(cur) + 1
}
func getChildrenSumSize(cur *Node) int {
return getSize(cur.children[0]) + getSize(cur.children[1])
}
func getChildrenSize(cur *Node) (int, int) {
return getSize(cur.children[0]), getSize(cur.children[1])
}
func getSize(cur *Node) int {
if cur == nil {
return 0
}
return cur.size
}
func (tree *Tree) fixSizeWithRemove(cur *Node) {
for cur != nil {
cur.size--
if cur.size > 8 {
factor := cur.size / 10 // or factor = 1
ls, rs := getChildrenSize(cur)
if rs >= ls*2+factor || ls >= rs*2+factor {
tree.fixSize(cur, ls, rs)
}
} else if cur.size == 3 {
if cur.children[0] == nil {
if cur.children[1].children[0] == nil {
tree.lrotate3(cur)
} else {
tree.lrrotate3(cur)
}
} else if cur.children[1] == nil {
if cur.children[0].children[1] == nil {
tree.rrotate3(cur)
} else {
tree.rlrotate3(cur)
}
}
}
cur = cur.parent
}
}
func (tree *Tree) fixSize(cur *Node, ls, rs int) {
if ls > rs {
llsize, lrsize := getChildrenSize(cur.children[0])
if lrsize > llsize {
tree.rlrotate(cur)
} else {
tree.rrotate(cur)
}
} else {
rlsize, rrsize := getChildrenSize(cur.children[1])
if rlsize > rrsize {
tree.lrrotate(cur)
} else {
tree.lrotate(cur)
}
}
}
func output(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
output(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
*str += spew.Sprint(node.key) + ":" + spew.Sprint(node.value) + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
output(node.children[0], newPrefix, true, str)
}
}
func outputfordebug(node *Node, prefix string, isTail bool, str *string) {
if node.children[1] != nil {
newPrefix := prefix
if isTail {
newPrefix += "│ "
} else {
newPrefix += " "
}
outputfordebug(node.children[1], newPrefix, false, str)
}
*str += prefix
if isTail {
*str += "└── "
} else {
*str += "┌── "
}
suffix := "("
parentv := ""
if node.parent == nil {
parentv = "nil"
} else {
parentv = spew.Sprint(node.parent.key)
}
suffix += parentv + "|" + spew.Sprint(node.size) + ")"
*str += spew.Sprint(node.key) + suffix + "\n"
if node.children[0] != nil {
newPrefix := prefix
if isTail {
newPrefix += " "
} else {
newPrefix += "│ "
}
outputfordebug(node.children[0], newPrefix, true, str)
}
}
func (tree *Tree) debugString() string {
str := "AVLTree\n"
if tree.root == nil {
return str + "nil"
}
outputfordebug(tree.root, "", true, &str)
return str
}

623
tree/vbtkey/vbtkey_test.go Normal file
View File

@@ -0,0 +1,623 @@
package vbtkey
import (
"bytes"
"encoding/gob"
"io/ioutil"
"log"
"testing"
"474420502.top/eson/structure/compare"
"github.com/huandu/skiplist"
"github.com/Pallinder/go-randomdata"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/trees/avltree"
"github.com/emirpasic/gods/trees/redblacktree"
)
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 TestIndexRange(t *testing.T) {
tree := New(compare.Int)
l := []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15}
for _, v := range l {
tree.Put(v, v)
}
// [3 7 14 14 14 15 16 17 20 21 30 40 40 40 40 50]
// t.Error(tree.Values(), tree.Size())
var result string
result = spew.Sprint(tree.IndexRange(0, 5))
if result != "[3 7 14 14 14 15] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(2, 5))
if result != "[14 14 14 15] true" {
t.Error(result)
}
result = spew.Sprint(tree.IndexRange(10, 100))
if result != "[30 40 40 40 40 50] false" {
t.Error(result)
}
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.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.IndexRange(5, 1)) // size = 16, index max = 15
if result != "[15 14 14 14 7] true" {
t.Error(result)
}
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.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.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.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) {
tree := New(compare.Int)
for _, v := range []int{7, 14, 14, 14, 16, 17, 20, 30, 21, 40, 50, 3, 40, 40, 40, 15} {
tree.Put(v, v)
}
var Result string
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(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(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 != "[17 <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> 7]" {
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
func TestPutComparatorRandom(t *testing.T) {
for n := 0; n < 300000; n++ {
tree := New(compare.Int)
godsavl := avltree.NewWithIntComparator()
content := ""
m := make(map[int]int)
for i := 0; len(m) < 10; i++ {
v := randomdata.Number(0, 65535)
if _, ok := m[v]; !ok {
m[v] = v
content += spew.Sprint(v) + ","
tree.Put(v, v)
godsavl.Put(v, v)
}
}
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(godsavl.Values())
if s1 != s2 {
t.Error(godsavl.String())
t.Error(tree.debugString())
t.Error(content, n)
break
}
}
}
func TestGet(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
tree.Put(v, v)
}
for _, v := range []int{2383, 7666, 3055, 39016, 57092, 27897, 36513, 1562, 22574, 23202} {
v, ok := tree.Get(v)
if !ok {
t.Error("the val not found ", v)
}
}
if v, ok := tree.Get(10000); ok {
t.Error("the val(1000) is not in tree, but is found", v)
}
}
func TestGetRange(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v, v)
}
// t.Error(tree.debugString())
// t.Error(tree.getArountNode(20))
// t.Error(tree.Values())
result := tree.GetRange(0, 20)
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(-5, -1)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(7, 20)
if spew.Sprint(result) != "[8 10 13 17]" {
t.Error(result)
}
result = tree.GetRange(30, 40)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(30, 60)
if spew.Sprint(result) != "[30 40]" {
t.Error(result)
}
result = tree.GetRange(40, 40)
if spew.Sprint(result) != "[40]" {
t.Error(result)
}
result = tree.GetRange(50, 60)
if spew.Sprint(result) != "[]" {
t.Error(result)
}
result = tree.GetRange(50, 1)
if spew.Sprint(result) != "[40 30 17 13 10 8 6 5 2 1]" {
t.Error(result)
}
result = tree.GetRange(30, 20)
if spew.Sprint(result) != "[30]" {
t.Error(result)
}
}
func TestTravalsal(t *testing.T) {
tree := New(compare.Int)
for _, v := range []int{5, 6, 8, 10, 13, 17, 1, 2, 40, 30} {
tree.Put(v, v)
}
i := 0
var result []interface{}
tree.Traversal(func(v interface{}) bool {
result = append(result, v)
i++
if i >= 10 {
return false
}
return true
})
if spew.Sprint(result) != "[1 2 5 6 8 10 13 17 30 40]" {
t.Error(result)
}
}
func TestRemoveAll(t *testing.T) {
ALL:
for c := 0; c < 5000; c++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 50; i++ {
v := randomdata.Number(0, 100000)
if _, ok := m[v]; !ok {
m[v] = v
l = append(l, v)
tree.Put(v, v)
gods.Put(v, v)
}
}
for i := 0; i < 50; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
s1 := spew.Sprint(tree.Values())
s2 := spew.Sprint(gods.Values())
if s1 != s2 {
t.Error("avl remove error", "avlsize = ", tree.Size())
t.Error(tree.root, i, l[i])
t.Error(s1)
t.Error(s2)
break ALL
}
}
}
}
func TestRemove(t *testing.T) {
ALL:
for N := 0; N < 5000; N++ {
tree := New(compare.Int)
gods := avltree.NewWithIntComparator()
var l []int
m := make(map[int]int)
for i := 0; len(l) < 20; i++ {
v := randomdata.Number(0, 100)
if _, ok := m[v]; !ok {
l = append(l, v)
m[v] = v
tree.Put(v, v)
gods.Put(v, v)
}
}
src1 := tree.String()
src2 := gods.String()
for i := 0; i < 20; i++ {
tree.Remove(l[i])
gods.Remove(l[i])
if tree.root != nil && spew.Sprint(gods.Values()) != spew.Sprint(tree.Values()) {
t.Error(src1)
t.Error(src2)
t.Error(tree.debugString())
t.Error(gods.String())
t.Error(l[i])
break ALL
}
}
}
}
func BenchmarkGetRange(b *testing.B) {
}
func BenchmarkIndexRange(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
b.ResetTimer()
b.StartTimer()
execCount := 5
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for range l {
tree.IndexRange(i, i+49)
}
}
}
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 {
sl.Get(v)
// e := sl.Get(v)
// var result [50]interface{}
// for i := 0; i < 50 && e != nil; i++ {
// result[i] = e.Value
// e = e.Next()
// }
}
}
}
func BenchmarkSkipListSet(b *testing.B) {
l := loadTestData()
execCount := 1
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
sl := skiplist.New(skiplist.Int)
for _, v := range l {
sl.Set(v, v)
}
}
}
func BenchmarkIterator(b *testing.B) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
b.ResetTimer()
b.StartTimer()
iter := tree.Iterator()
b.N = 0
for iter.Next() {
b.N++
}
for iter.Prev() {
b.N++
}
for iter.Next() {
b.N++
}
b.Log(b.N, len(l))
}
func BenchmarkRemove(b *testing.B) {
tree := New(compare.Int)
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 BenchmarkGodsRemove(b *testing.B) {
tree := avltree.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 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) {
tree := New(compare.Int)
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], i)
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsRBGet(b *testing.B) {
tree := redblacktree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], i)
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkGodsAvlGet(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.N = len(l)
for i := 0; i < b.N; i++ {
tree.Put(l[i], i)
}
b.ResetTimer()
b.StartTimer()
execCount := 10
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
for _, v := range l {
tree.Get(v)
}
}
}
func BenchmarkPut(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 50
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
tree := New(compare.Int)
for _, v := range l {
tree.Put(v, v)
}
}
}
func TestPutStable(t *testing.T) {
}
func BenchmarkGodsRBPut(b *testing.B) {
l := loadTestData()
b.ResetTimer()
b.StartTimer()
execCount := 50
b.N = len(l) * execCount
for i := 0; i < execCount; i++ {
tree := redblacktree.NewWithIntComparator()
for _, v := range l {
tree.Put(v, v)
}
}
}
func BenchmarkGodsPut(b *testing.B) {
tree := avltree.NewWithIntComparator()
l := loadTestData()
b.ResetTimer()
b.StartTimer()
b.N = len(l)
for _, v := range l {
tree.Put(v, v)
}
}