diff --git a/heap/heap.go b/heap/heap.go new file mode 100644 index 0000000..35c27ff --- /dev/null +++ b/heap/heap.go @@ -0,0 +1,16 @@ +package heap + +import ( + "474420502.top/eson/structure/compare" +) + +type Heap struct { + size int + cap int + elements []interface{} + Compare compare.Compare +} + +func New(Compare compare.Compare) *Heap { + return &Heap{Compare: Compare, cap: 8} +} diff --git a/sparse_array/array2.go b/sparse_array/array2.go new file mode 100644 index 0000000..40f049f --- /dev/null +++ b/sparse_array/array2.go @@ -0,0 +1,93 @@ +package sparse + +type Array2 struct { + sizes []int + ysize int + xsize int + data [][]interface{} +} + +func New() *Array2 { + arr := &Array2{ysize: 8, xsize: 8} + arr.sizes = make([]int, arr.ysize, arr.ysize) + arr.data = make([][]interface{}, arr.ysize, arr.ysize) + return arr +} + +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) + return arr +} + +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, struct{}{}) + } else { + result = append(result, v) + } + } + } else { + for i := 0; i < arr.ysize; i++ { + result = append(result, nil) + } + } + } + + return result +} + +func (arr *Array2) Set(idx int, value interface{}) { + yindex := idx / arr.ysize + xindex := idx % arr.xsize + + ydata := arr.data[yindex] + if ydata == nil { + ydata = make([]interface{}, arr.xsize, arr.xsize) + arr.data[yindex] = ydata + } + + if ydata[xindex] == nil { + arr.sizes[yindex]++ + } + + ydata[xindex] = value +} + +func (arr *Array2) Get(idx int) (interface{}, bool) { + yindex := idx / arr.ysize + xindex := idx % arr.xsize + + ydata := arr.data[yindex] + if ydata == nil { + return nil, false + } + v := ydata[xindex] + return v, v != nil +} + +func (arr *Array2) Del(idx int) (interface{}, bool) { + yindex := idx / arr.ysize + xindex := idx % arr.xsize + + ydata := arr.data[yindex] + if ydata == nil { + return nil, false + } + v := ydata[xindex] + ydata[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_test.go b/sparse_array/array2_test.go new file mode 100644 index 0000000..43ec894 --- /dev/null +++ b/sparse_array/array2_test.go @@ -0,0 +1,154 @@ +package sparse + +import ( + "testing" + + "github.com/davecgh/go-spew/spew" + + "github.com/Pallinder/go-randomdata" +) + +func TestSet(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.Values()) + 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 TestGet(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 TestDel(t *testing.T) { + arr := NewWithCap(4, 4) + 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.Values()) + if result != "[ {} 5 6 {} {} {} {} 15]" { + t.Error(result) + } + + arr.Del(5) + result = spew.Sprint(arr.Values()) + if result != "[ {} {} 6 {} {} {} {} 15]" { + t.Error(result) + } + + arr.Del(6) + result = spew.Sprint(arr.Values()) + if result != "[ {} {} {} 15]" { + t.Error(result) + } + + arr.Del(15) + result = spew.Sprint(arr.Values()) + 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(16) +} + +func BenchmarkSet(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 BenchmarkGet(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 BenchmarkDel(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) + } + +}