From 3b54163d0656c38d965428d014ab2473b3e12eff Mon Sep 17 00:00:00 2001 From: eson <474420502@qq.com> Date: Fri, 12 Apr 2019 04:48:54 +0800 Subject: [PATCH] =?UTF-8?q?array=20=E8=AE=A1=E7=AE=97=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sparse_array/{ => array2}/array2.go | 23 ++-- sparse_array/{ => array2}/array2_test.go | 14 +- sparse_array/array3.go | 153 ++++++++++++++++++++++ sparse_array/array3_test.go | 155 +++++++++++++++++++++++ 4 files changed, 325 insertions(+), 20 deletions(-) rename sparse_array/{ => array2}/array2.go (80%) rename sparse_array/{ => array2}/array2_test.go (91%) create mode 100644 sparse_array/array3.go create mode 100644 sparse_array/array3_test.go diff --git a/sparse_array/array2.go b/sparse_array/array2/array2.go similarity index 80% rename from sparse_array/array2.go rename to sparse_array/array2/array2.go index 40f049f..e911131 100644 --- a/sparse_array/array2.go +++ b/sparse_array/array2/array2.go @@ -1,4 +1,4 @@ -package sparse +package array2 type Array2 struct { sizes []int @@ -8,10 +8,7 @@ type Array2 struct { } 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 + return NewWithCap(8, 8) } func NewWithCap(ysize, xsize int) *Array2 { @@ -44,7 +41,7 @@ func (arr *Array2) Values() []interface{} { func (arr *Array2) Set(idx int, value interface{}) { yindex := idx / arr.ysize - xindex := idx % arr.xsize + xindex := idx % arr.ysize ydata := arr.data[yindex] if ydata == nil { @@ -61,33 +58,33 @@ func (arr *Array2) Set(idx int, value interface{}) { func (arr *Array2) Get(idx int) (interface{}, bool) { yindex := idx / arr.ysize - xindex := idx % arr.xsize + xindex := idx % arr.ysize ydata := arr.data[yindex] if ydata == nil { return nil, false } - v := ydata[xindex] - return v, v != nil + xdata := ydata[xindex] + return xdata, xdata != nil } func (arr *Array2) Del(idx int) (interface{}, bool) { yindex := idx / arr.ysize - xindex := idx % arr.xsize + xindex := idx % arr.ysize ydata := arr.data[yindex] if ydata == nil { return nil, false } - v := ydata[xindex] + xdata := ydata[xindex] ydata[xindex] = nil - isnil := v != nil + isnil := xdata != nil if isnil { arr.sizes[yindex]-- if arr.sizes[yindex] == 0 { arr.data[yindex] = nil } } - return v, isnil + return xdata, isnil } diff --git a/sparse_array/array2_test.go b/sparse_array/array2/array2_test.go similarity index 91% rename from sparse_array/array2_test.go rename to sparse_array/array2/array2_test.go index 43ec894..5dbffeb 100644 --- a/sparse_array/array2_test.go +++ b/sparse_array/array2/array2_test.go @@ -1,4 +1,4 @@ -package sparse +package array2 import ( "testing" @@ -8,7 +8,7 @@ import ( "github.com/Pallinder/go-randomdata" ) -func TestSet(t *testing.T) { +func TestArray2Set(t *testing.T) { arr := NewWithCap(4, 4) l := []int{0, 6, 5, 15} for _, v := range l { @@ -30,7 +30,7 @@ func TestSet(t *testing.T) { arr.Set(16, 16) } -func TestGet(t *testing.T) { +func TestArray2Get(t *testing.T) { arr := New() for i := 0; i < 64; i++ { arr.Set(i, i) @@ -55,7 +55,7 @@ func TestGet(t *testing.T) { arr.Get(64) } -func TestDel(t *testing.T) { +func TestArray2Del(t *testing.T) { arr := NewWithCap(4, 4) l := []int{0, 6, 5, 15} for _, v := range l { @@ -97,7 +97,7 @@ func TestDel(t *testing.T) { arr.Del(16) } -func BenchmarkSet(b *testing.B) { +func BenchmarkArray2Set(b *testing.B) { arr := NewWithCap(1000, 100) b.N = 500000000 @@ -116,7 +116,7 @@ func BenchmarkSet(b *testing.B) { } -func BenchmarkGet(b *testing.B) { +func BenchmarkArray2Get(b *testing.B) { arr := NewWithCap(1000, 100) b.N = 500000000 @@ -135,7 +135,7 @@ func BenchmarkGet(b *testing.B) { } -func BenchmarkDel(b *testing.B) { +func BenchmarkArray2Del(b *testing.B) { arr := NewWithCap(1000, 100) b.N = 500000000 diff --git a/sparse_array/array3.go b/sparse_array/array3.go new file mode 100644 index 0000000..6bfcdf1 --- /dev/null +++ b/sparse_array/array3.go @@ -0,0 +1,153 @@ +package array3 + +import ( + "log" + + "github.com/davecgh/go-spew/spew" +) + +type Array3 struct { + ysizes []int + xsizes [][]int + xyproduct int + zsize int + ysize int + xsize int + data [][][]interface{} +} + +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) + return arr +} + +func (arr *Array3) Values() []interface{} { + var result []interface{} + spew.Println(arr.data) + 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) Set(idx int, value interface{}) { + + zindex := idx / arr.xyproduct + nidx := (idx % arr.xyproduct) + yindex := nidx / arr.ysize + xindex := nidx % arr.ysize + + log.Println(zindex, nidx, yindex, xindex) + + zdata := arr.data[zindex] + if zdata == nil { + zdata = make([][]interface{}, arr.ysize, arr.ysize) + arr.data[yindex] = zdata + + } + + ydata := zdata[yindex] + if ydata == nil { + ydata = make([]interface{}, arr.xsize, arr.xsize) + zdata[yindex] = ydata + arr.ysizes[zindex]++ + } + + xdata := ydata[xindex] + if xdata == nil { + arr.xsizes[zindex][yindex]++ + } + ydata[xindex] = value +} + +func (arr *Array3) Get(idx int) (interface{}, bool) { + zindex := idx / arr.xyproduct + nextsize := (idx % arr.xyproduct) + yindex := nextsize / arr.ysize + xindex := nextsize % arr.ysize + + zdata := arr.data[zindex] + if zdata == nil { + return nil, false + } + + ydata := zdata[yindex] + if ydata == nil { + return nil, false + } + + xdata := ydata[xindex] + return xdata, xdata != nil +} + +func (arr *Array3) Del(idx int) (interface{}, bool) { + zindex := idx / arr.xyproduct + nextsize := (idx % arr.xyproduct) + yindex := nextsize / arr.ysize + xindex := nextsize % arr.ysize + + zdata := arr.data[zindex] + if zdata == nil { + return nil, false + } + + ydata := zdata[yindex] + if ydata == nil { + return nil, false + } + + xdata := ydata[xindex] + ydata[xindex] = nil + + isnotnil := xdata != 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 xdata, isnotnil +} diff --git a/sparse_array/array3_test.go b/sparse_array/array3_test.go new file mode 100644 index 0000000..5f570df --- /dev/null +++ b/sparse_array/array3_test.go @@ -0,0 +1,155 @@ +package array3 + +import ( + "testing" + + "github.com/davecgh/go-spew/spew" + + "github.com/Pallinder/go-randomdata" +) + +func TestSet(t *testing.T) { + arr := NewWithCap(3, 3, 3) + l := []int{0, 6, 5, 9, 15} + for _, v := range l { + arr.Set(v, v) + spew.Sprint(arr.Values()) + } + + 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, 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(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 BenchmarkGet(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 BenchmarkDel(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) + } + +}