commit 368447c31df853746e51c07d92ac08c94bb32d84 Author: eson <474420502@qq.com> Date: Wed May 8 10:42:51 2019 +0800 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 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f86e4a7 --- /dev/null +++ b/.gitignore @@ -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 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d449d3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..b7a80c2 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# structure + diff --git a/compare/compare.go b/compare/compare.go new file mode 100644 index 0000000..79c77ee --- /dev/null +++ b/compare/compare.go @@ -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 + } +} diff --git a/for_test.go b/for_test.go new file mode 100644 index 0000000..d2d038e --- /dev/null +++ b/for_test.go @@ -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 +} diff --git a/heap/heap.go b/heap/heap.go new file mode 100644 index 0000000..f01ab07 --- /dev/null +++ b/heap/heap.go @@ -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 +} diff --git a/heap/heap_test.go b/heap/heap_test.go new file mode 100644 index 0000000..cd70d26 --- /dev/null +++ b/heap/heap_test.go @@ -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 +} diff --git a/interface.go b/interface.go new file mode 100644 index 0000000..6fe4564 --- /dev/null +++ b/interface.go @@ -0,0 +1 @@ +package structure diff --git a/lastack/lastack.go b/lastack/lastack.go new file mode 100644 index 0000000..a0febff --- /dev/null +++ b/lastack/lastack.go @@ -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 +} diff --git a/lastack/lastack_test.go b/lastack/lastack_test.go new file mode 100644 index 0000000..808b997 --- /dev/null +++ b/lastack/lastack_test.go @@ -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() + } +} diff --git a/list/list.go b/list/list.go new file mode 100644 index 0000000..6c1b29c --- /dev/null +++ b/list/list.go @@ -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 + } + } +} diff --git a/list/list_test.go b/list/list_test.go new file mode 100644 index 0000000..da0ce10 --- /dev/null +++ b/list/list_test.go @@ -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()) + } +} diff --git a/map/hashmap/hashmap.go b/map/hashmap/hashmap.go new file mode 100644 index 0000000..56cd19f --- /dev/null +++ b/map/hashmap/hashmap.go @@ -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 +} diff --git a/map/hashmap/hashmap_test.go b/map/hashmap/hashmap_test.go new file mode 100644 index 0000000..853bf65 --- /dev/null +++ b/map/hashmap/hashmap_test.go @@ -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() +// } diff --git a/priority_list/iterator.go b/priority_list/iterator.go new file mode 100644 index 0000000..cc1738d --- /dev/null +++ b/priority_list/iterator.go @@ -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 +} diff --git a/priority_list/priority_list.go b/priority_list/priority_list.go new file mode 100644 index 0000000..70b5a5b --- /dev/null +++ b/priority_list/priority_list.go @@ -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 +} diff --git a/priority_list/priority_list_test.go b/priority_list/priority_list_test.go new file mode 100644 index 0000000..6d5eb51 --- /dev/null +++ b/priority_list/priority_list_test.go @@ -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) + } + } +} diff --git a/priority_queue/iterator.go b/priority_queue/iterator.go new file mode 100644 index 0000000..bee120c --- /dev/null +++ b/priority_queue/iterator.go @@ -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) + } + } +} diff --git a/priority_queue/priority_queue.go b/priority_queue/priority_queue.go new file mode 100644 index 0000000..18bfd14 --- /dev/null +++ b/priority_queue/priority_queue.go @@ -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() +} diff --git a/priority_queue/priority_queue_test.go b/priority_queue/priority_queue_test.go new file mode 100644 index 0000000..6957a4f --- /dev/null +++ b/priority_queue/priority_queue_test.go @@ -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 53]" { + t.Error(result) + } + + result = spew.Sprint(pq.GetAround(1)) + if result != "[ 1 4]" { + t.Error(result) + } + + result = spew.Sprint(pq.GetAround(90)) + if result != "[78 90 ]" { + t.Error(result) + } + + result = spew.Sprint(pq.GetAround(0)) + if result != "[ 1]" { + t.Error(result) + } + + result = spew.Sprint(pq.GetAround(100)) + if result != "[90 ]" { + 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() + } +} diff --git a/priority_queue/vbt.go b/priority_queue/vbt.go new file mode 100644 index 0000000..75dcceb --- /dev/null +++ b/priority_queue/vbt.go @@ -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 +} diff --git a/priority_queue/vbt_test.go b/priority_queue/vbt_test.go new file mode 100644 index 0000000..f366461 --- /dev/null +++ b/priority_queue/vbt_test.go @@ -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 != "[ 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 ]" { + 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 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 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 != "[ 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 ]" { + 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) + } +} diff --git a/priority_queuekey/iterator.go b/priority_queuekey/iterator.go new file mode 100644 index 0000000..b33b4b5 --- /dev/null +++ b/priority_queuekey/iterator.go @@ -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) + } + } +} diff --git a/priority_queuekey/priority_queuekey.go b/priority_queuekey/priority_queuekey.go new file mode 100644 index 0000000..bed775d --- /dev/null +++ b/priority_queuekey/priority_queuekey.go @@ -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() +} diff --git a/priority_queuekey/priority_queuekey_test.go b/priority_queuekey/priority_queuekey_test.go new file mode 100644 index 0000000..58755d3 --- /dev/null +++ b/priority_queuekey/priority_queuekey_test.go @@ -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 53]" { + t.Error(result) + } + + result = spew.Sprint(pq.GetAround(1)) + if result != "[ 1 4]" { + t.Error(result) + } + + result = spew.Sprint(pq.GetAround(90)) + if result != "[78 90 ]" { + t.Error(result) + } + + result = spew.Sprint(pq.GetAround(0)) + if result != "[ 1]" { + t.Error(result) + } + + result = spew.Sprint(pq.GetAround(100)) + if result != "[90 ]" { + 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() + } +} diff --git a/priority_queuekey/vbt.go b/priority_queuekey/vbt.go new file mode 100644 index 0000000..c627b05 --- /dev/null +++ b/priority_queuekey/vbt.go @@ -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 +} diff --git a/priority_queuekey/vbt_test.go b/priority_queuekey/vbt_test.go new file mode 100644 index 0000000..be10d94 --- /dev/null +++ b/priority_queuekey/vbt_test.go @@ -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 != "[ 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 ]" { + 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 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 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 != "[ 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 ]" { + 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) + } +} diff --git a/set/hashset/hashset.go b/set/hashset/hashset.go new file mode 100644 index 0000000..06754c7 --- /dev/null +++ b/set/hashset/hashset.go @@ -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 +} diff --git a/set/hashset/hashset_test.go b/set/hashset/hashset_test.go new file mode 100644 index 0000000..e2a8874 --- /dev/null +++ b/set/hashset/hashset_test.go @@ -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") + } +} diff --git a/set/treeset/treeset.go b/set/treeset/treeset.go new file mode 100644 index 0000000..7e48b08 --- /dev/null +++ b/set/treeset/treeset.go @@ -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 +} diff --git a/set/treeset/treeset_test.go b/set/treeset/treeset_test.go new file mode 100644 index 0000000..3e1768e --- /dev/null +++ b/set/treeset/treeset_test.go @@ -0,0 +1 @@ +package treeset diff --git a/sparse_array/array2/array2.go b/sparse_array/array2/array2.go new file mode 100644 index 0000000..ca0bbef --- /dev/null +++ b/sparse_array/array2/array2.go @@ -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 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 +} diff --git a/sparse_array/array2/array2_test.go b/sparse_array/array2/array2_test.go new file mode 100644 index 0000000..ac05cfd --- /dev/null +++ b/sparse_array/array2/array2_test.go @@ -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 {} {} {} {} 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 {} {} {} {} 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 {} {} {} {} 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 != "[ 6 {} {} {} {} {} {} {} {} 15 {} {}]" { + t.Error(arr.data) + t.Error(result) + } + + arr.Del(6) + result = spew.Sprint(arr.debugValues()) + if result != "[ {} {} {} 15 {} {}]" { + t.Error(result) + } + + arr.Del(15) + result = spew.Sprint(arr.debugValues()) + if result != "[ ]" { + 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 {} {} {} {} 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) + } + +} diff --git a/sparse_array/array3/array3.go b/sparse_array/array3/array3.go new file mode 100644 index 0000000..ad78953 --- /dev/null +++ b/sparse_array/array3/array3.go @@ -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 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 +} diff --git a/sparse_array/array3/array3_test.go b/sparse_array/array3/array3_test.go new file mode 100644 index 0000000..8105cc3 --- /dev/null +++ b/sparse_array/array3/array3_test.go @@ -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 {} 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 {} {} {} {} 15] + var result string + + arr.Del(0) + result = spew.Sprint(arr.debugValues()) + if result != "[ {} {} 5 6 {} {} {} {} 11]" { + t.Error(arr.data) + t.Error(result) + } + + arr.Del(5) + result = spew.Sprint(arr.debugValues()) + if result != "[ 6 {} {} {} {} 11]" { + t.Error(arr.data) + t.Error(result) + } + + arr.Del(6) + result = spew.Sprint(arr.debugValues()) + if result != "[ {} {} 11]" { + t.Error(result) + } + + arr.Del(11) + result = spew.Sprint(arr.debugValues()) + if result != "[ ]" { + 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) + } +} diff --git a/sparse_array/arrayn/arrayn.go b/sparse_array/arrayn/arrayn.go new file mode 100644 index 0000000..f29317f --- /dev/null +++ b/sparse_array/arrayn/arrayn.go @@ -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 +} diff --git a/sparse_array/arrayn/arrayn_test.go b/sparse_array/arrayn/arrayn_test.go new file mode 100644 index 0000000..4da1a5d --- /dev/null +++ b/sparse_array/arrayn/arrayn_test.go @@ -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 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 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 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 != "[ ]" { + 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 5 6 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) + } + } +} diff --git a/stack/stack.go b/stack/stack.go new file mode 100644 index 0000000..1972a3c --- /dev/null +++ b/stack/stack.go @@ -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 +} diff --git a/stack/stack_test.go b/stack/stack_test.go new file mode 100644 index 0000000..57b3e4c --- /dev/null +++ b/stack/stack_test.go @@ -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() + } +} diff --git a/tree/avl/avl.go b/tree/avl/avl.go new file mode 100644 index 0000000..e60050d --- /dev/null +++ b/tree/avl/avl.go @@ -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 +} diff --git a/tree/avl/avl_test.go b/tree/avl/avl_test.go new file mode 100644 index 0000000..5d28088 --- /dev/null +++ b/tree/avl/avl_test.go @@ -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 != "[ 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 ]" { + 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 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 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 != "[ 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 ]" { + 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) + } +} diff --git a/tree/avl/iterator.go b/tree/avl/iterator.go new file mode 100644 index 0000000..501ae6b --- /dev/null +++ b/tree/avl/iterator.go @@ -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) + } + } +} diff --git a/tree/avldup/avldup.go b/tree/avldup/avldup.go new file mode 100644 index 0000000..4cd7855 --- /dev/null +++ b/tree/avldup/avldup.go @@ -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 +} diff --git a/tree/avldup/avldup_test.go b/tree/avldup/avldup_test.go new file mode 100644 index 0000000..f37ee66 --- /dev/null +++ b/tree/avldup/avldup_test.go @@ -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 != "[ 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 ]" { + 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 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 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 != "[ 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 ]" { + 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) + } +} diff --git a/tree/avldup/iterator.go b/tree/avldup/iterator.go new file mode 100644 index 0000000..3fe6b63 --- /dev/null +++ b/tree/avldup/iterator.go @@ -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) + } + } +} diff --git a/tree/avlkey/avlkey.go b/tree/avlkey/avlkey.go new file mode 100644 index 0000000..6efbf4f --- /dev/null +++ b/tree/avlkey/avlkey.go @@ -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 +} diff --git a/tree/avlkey/avlkey_test.go b/tree/avlkey/avlkey_test.go new file mode 100644 index 0000000..c497e0b --- /dev/null +++ b/tree/avlkey/avlkey_test.go @@ -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 != "[ 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 ]" { + 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 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 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 != "[ 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 ]" { + 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) + } +} diff --git a/tree/avlkey/iterator.go b/tree/avlkey/iterator.go new file mode 100644 index 0000000..555efa8 --- /dev/null +++ b/tree/avlkey/iterator.go @@ -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) + } + } +} diff --git a/tree/avlkeydup/avlkeydup.go b/tree/avlkeydup/avlkeydup.go new file mode 100644 index 0000000..a354745 --- /dev/null +++ b/tree/avlkeydup/avlkeydup.go @@ -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 +} diff --git a/tree/avlkeydup/avlkeydup_test.go b/tree/avlkeydup/avlkeydup_test.go new file mode 100644 index 0000000..41ed0e2 --- /dev/null +++ b/tree/avlkeydup/avlkeydup_test.go @@ -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 != "[ 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 ]" { + 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 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 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 != "[ 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 ]" { + 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) + } +} diff --git a/tree/avlkeydup/iterator.go b/tree/avlkeydup/iterator.go new file mode 100644 index 0000000..ffa1a24 --- /dev/null +++ b/tree/avlkeydup/iterator.go @@ -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) + } + } +} diff --git a/tree/vbt/iterator.go b/tree/vbt/iterator.go new file mode 100644 index 0000000..eec37bf --- /dev/null +++ b/tree/vbt/iterator.go @@ -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) + } + } +} diff --git a/tree/vbt/vbt.go b/tree/vbt/vbt.go new file mode 100644 index 0000000..207f136 --- /dev/null +++ b/tree/vbt/vbt.go @@ -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 +} diff --git a/tree/vbt/vbt_test.go b/tree/vbt/vbt_test.go new file mode 100644 index 0000000..751a8ad --- /dev/null +++ b/tree/vbt/vbt_test.go @@ -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 != "[ 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 ]" { + 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 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 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 != "[ 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 ]" { + 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) + } +} diff --git a/tree/vbtkey/iterator.go b/tree/vbtkey/iterator.go new file mode 100644 index 0000000..4f41655 --- /dev/null +++ b/tree/vbtkey/iterator.go @@ -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) + } + } +} diff --git a/tree/vbtkey/vbtkey.go b/tree/vbtkey/vbtkey.go new file mode 100644 index 0000000..fb48e2b --- /dev/null +++ b/tree/vbtkey/vbtkey.go @@ -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 +} diff --git a/tree/vbtkey/vbtkey_test.go b/tree/vbtkey/vbtkey_test.go new file mode 100644 index 0000000..fda305e --- /dev/null +++ b/tree/vbtkey/vbtkey_test.go @@ -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 != "[ 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 ]" { + 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 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 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 != "[ 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 ]" { + 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) + } +}