From 6389722a0c67dfe1172a37b5a62258a03101ee59 Mon Sep 17 00:00:00 2001 From: eson <474420502@qq.com> Date: Sat, 13 Apr 2019 03:35:18 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=20ArrayN=20del=20=E6=93=8D?= =?UTF-8?q?=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sparse_array/array2/array2.go | 46 ++++----- sparse_array/array2/array2_test.go | 75 ++++++++++++-- sparse_array/{ => array3}/array3.go | 81 +++++++-------- sparse_array/{ => array3}/array3_test.go | 97 +++++++++++++---- sparse_array/arrayn/arrayn.go | 126 +++++++++++++++++++++++ sparse_array/arrayn/arrayn_test.go | 53 ++++++++++ 6 files changed, 382 insertions(+), 96 deletions(-) rename sparse_array/{ => array3}/array3.go (69%) rename sparse_array/{ => array3}/array3_test.go (56%) create mode 100644 sparse_array/arrayn/arrayn.go create mode 100644 sparse_array/arrayn/arrayn_test.go diff --git a/sparse_array/array2/array2.go b/sparse_array/array2/array2.go index e911131..5150479 100644 --- a/sparse_array/array2/array2.go +++ b/sparse_array/array2/array2.go @@ -30,7 +30,7 @@ func (arr *Array2) Values() []interface{} { } } } else { - for i := 0; i < arr.ysize; i++ { + for i := 0; i < arr.xsize; i++ { result = append(result, nil) } } @@ -40,51 +40,51 @@ func (arr *Array2) Values() []interface{} { } func (arr *Array2) Set(idx int, value interface{}) { - yindex := idx / arr.ysize - xindex := idx % arr.ysize + yindex := idx / arr.xsize + xindex := idx % arr.xsize - ydata := arr.data[yindex] - if ydata == nil { - ydata = make([]interface{}, arr.xsize, arr.xsize) - arr.data[yindex] = ydata + xdata := arr.data[yindex] + if xdata == nil { + xdata = make([]interface{}, arr.xsize, arr.xsize) + arr.data[yindex] = xdata } - if ydata[xindex] == nil { + if xdata[xindex] == nil { arr.sizes[yindex]++ } - ydata[xindex] = value + xdata[xindex] = value } func (arr *Array2) Get(idx int) (interface{}, bool) { - yindex := idx / arr.ysize - xindex := idx % arr.ysize + yindex := idx / arr.xsize + xindex := idx % arr.xsize - ydata := arr.data[yindex] - if ydata == nil { + xdata := arr.data[yindex] + if xdata == nil { return nil, false } - xdata := ydata[xindex] - return xdata, xdata != nil + v := xdata[xindex] + return v, v != nil } func (arr *Array2) Del(idx int) (interface{}, bool) { - yindex := idx / arr.ysize - xindex := idx % arr.ysize + yindex := idx / arr.xsize + xindex := idx % arr.xsize - ydata := arr.data[yindex] - if ydata == nil { + xdata := arr.data[yindex] + if xdata == nil { return nil, false } - xdata := ydata[xindex] - ydata[xindex] = nil + v := xdata[xindex] + xdata[xindex] = nil - isnil := xdata != nil + isnil := v != nil if isnil { arr.sizes[yindex]-- if arr.sizes[yindex] == 0 { arr.data[yindex] = nil } } - return xdata, isnil + return v, isnil } diff --git a/sparse_array/array2/array2_test.go b/sparse_array/array2/array2_test.go index 5dbffeb..ed1df15 100644 --- a/sparse_array/array2/array2_test.go +++ b/sparse_array/array2/array2_test.go @@ -8,7 +8,7 @@ import ( "github.com/Pallinder/go-randomdata" ) -func TestArray2Set(t *testing.T) { +func testSet1(t *testing.T) { arr := NewWithCap(4, 4) l := []int{0, 6, 5, 15} for _, v := range l { @@ -30,7 +30,34 @@ func TestArray2Set(t *testing.T) { arr.Set(16, 16) } -func TestArray2Get(t *testing.T) { +func testSet2(t *testing.T) { + arr := NewWithCap(3, 6) + 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 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) @@ -55,8 +82,38 @@ func TestArray2Get(t *testing.T) { 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(4, 4) + arr := NewWithCap(3, 6) l := []int{0, 6, 5, 15} for _, v := range l { arr.Set(v, v) @@ -66,25 +123,27 @@ func TestArray2Del(t *testing.T) { arr.Del(0) result = spew.Sprint(arr.Values()) - if result != "[ {} 5 6 {} {} {} {} 15]" { + if result != "[{} {} {} {} {} 5 6 {} {} {} {} {} {} {} {} 15 {} {}]" { + t.Error(arr.data) t.Error(result) } arr.Del(5) result = spew.Sprint(arr.Values()) - if result != "[ {} {} 6 {} {} {} {} 15]" { + if result != "[ 6 {} {} {} {} {} {} {} {} 15 {} {}]" { + t.Error(arr.data) t.Error(result) } arr.Del(6) result = spew.Sprint(arr.Values()) - if result != "[ {} {} {} 15]" { + if result != "[ {} {} {} 15 {} {}]" { t.Error(result) } arr.Del(15) result = spew.Sprint(arr.Values()) - if result != "[ ]" { + if result != "[ ]" { t.Error(result) } @@ -94,7 +153,7 @@ func TestArray2Del(t *testing.T) { } }() - arr.Del(16) + arr.Del(18) } func BenchmarkArray2Set(b *testing.B) { diff --git a/sparse_array/array3.go b/sparse_array/array3/array3.go similarity index 69% rename from sparse_array/array3.go rename to sparse_array/array3/array3.go index 6bfcdf1..66873b4 100644 --- a/sparse_array/array3.go +++ b/sparse_array/array3/array3.go @@ -1,11 +1,5 @@ package array3 -import ( - "log" - - "github.com/davecgh/go-spew/spew" -) - type Array3 struct { ysizes []int xsizes [][]int @@ -37,7 +31,6 @@ func NewWithCap(zsize, ysize, xsize int) *Array3 { func (arr *Array3) Values() []interface{} { var result []interface{} - spew.Println(arr.data) for _, z := range arr.data { if z != nil { @@ -67,75 +60,71 @@ func (arr *Array3) Values() []interface{} { } 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 + 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 } - ydata := zdata[yindex] - if ydata == nil { - ydata = make([]interface{}, arr.xsize, arr.xsize) - zdata[yindex] = ydata + xdata := ydata[yindex] + if xdata == nil { + xdata = make([]interface{}, arr.xsize, arr.xsize) + ydata[yindex] = xdata arr.ysizes[zindex]++ } - xdata := ydata[xindex] - if xdata == nil { + v := xdata[xindex] + if v == nil { arr.xsizes[zindex][yindex]++ } - ydata[xindex] = value + xdata[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 + yindex := nextsize / arr.xsize + xindex := nextsize % arr.xsize - zdata := arr.data[zindex] - if zdata == nil { - return nil, false - } - - ydata := zdata[yindex] + ydata := arr.data[zindex] if ydata == nil { return nil, false } - xdata := ydata[xindex] - return xdata, xdata != nil + xdata := ydata[yindex] + if xdata == nil { + return nil, false + } + + v := xdata[xindex] + return v, v != 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 + yindex := nextsize / arr.xsize + xindex := nextsize % arr.xsize - zdata := arr.data[zindex] - if zdata == nil { - return nil, false - } - - ydata := zdata[yindex] + ydata := arr.data[zindex] if ydata == nil { return nil, false } - xdata := ydata[xindex] - ydata[xindex] = nil + xdata := ydata[yindex] + if xdata == nil { + return nil, false + } - isnotnil := xdata != nil + v := xdata[xindex] + xdata[xindex] = nil + + isnotnil := v != nil if isnotnil { arr.xsizes[zindex][yindex]-- @@ -149,5 +138,5 @@ func (arr *Array3) Del(idx int) (interface{}, bool) { } } - return xdata, isnotnil + return v, isnotnil } diff --git a/sparse_array/array3_test.go b/sparse_array/array3/array3_test.go similarity index 56% rename from sparse_array/array3_test.go rename to sparse_array/array3/array3_test.go index 5f570df..e378d0e 100644 --- a/sparse_array/array3_test.go +++ b/sparse_array/array3/array3_test.go @@ -8,17 +8,16 @@ import ( "github.com/Pallinder/go-randomdata" ) -func TestSet(t *testing.T) { - arr := NewWithCap(3, 3, 3) - l := []int{0, 6, 5, 9, 15} +func testSet1(t *testing.T) { + arr := NewWithCap(2, 2, 2) + l := []int{0, 1, 7} 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]" { + if result != "[0 1 {} 7]" { t.Error(result) } @@ -28,10 +27,38 @@ func TestSet(t *testing.T) { } }() - arr.Set(16, 16) + arr.Set(8, 8) } -func TestGet(t *testing.T) { +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 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) @@ -56,9 +83,39 @@ func TestGet(t *testing.T) { arr.Get(64) } -func TestDel(t *testing.T) { - arr := NewWithCap(4, 4, 4) - l := []int{0, 6, 5, 15} +func testArray2Get2(t *testing.T) { + arr := NewWithCap(4, 3, 3) + 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(2, 2, 3) + l := []int{0, 6, 5, 11} for _, v := range l { arr.Set(v, v) } @@ -67,25 +124,27 @@ func TestDel(t *testing.T) { arr.Del(0) result = spew.Sprint(arr.Values()) - if result != "[ {} 5 6 {} {} {} {} 15]" { + if result != "[ {} {} 5 6 {} {} {} {} 11]" { + t.Error(arr.data) t.Error(result) } arr.Del(5) result = spew.Sprint(arr.Values()) - if result != "[ {} {} 6 {} {} {} {} 15]" { + if result != "[ 6 {} {} {} {} 11]" { + t.Error(arr.data) t.Error(result) } arr.Del(6) result = spew.Sprint(arr.Values()) - if result != "[ {} {} {} 15]" { + if result != "[ {} {} 11]" { t.Error(result) } - arr.Del(15) + arr.Del(11) result = spew.Sprint(arr.Values()) - if result != "[ ]" { + if result != "[ ]" { t.Error(result) } @@ -95,10 +154,10 @@ func TestDel(t *testing.T) { } }() - arr.Del(16) + arr.Del(18) } -func BenchmarkSet(b *testing.B) { +func BenchmarkArray2Set(b *testing.B) { arr := NewWithCap(100, 100, 10) b.N = 500000000 @@ -117,7 +176,7 @@ func BenchmarkSet(b *testing.B) { } -func BenchmarkGet(b *testing.B) { +func BenchmarkArray2Get(b *testing.B) { arr := NewWithCap(100, 100, 10) b.N = 500000000 @@ -136,7 +195,7 @@ func BenchmarkGet(b *testing.B) { } -func BenchmarkDel(b *testing.B) { +func BenchmarkArray2Del(b *testing.B) { arr := NewWithCap(100, 100, 10) b.N = 500000000 diff --git a/sparse_array/arrayn/arrayn.go b/sparse_array/arrayn/arrayn.go new file mode 100644 index 0000000..d74804a --- /dev/null +++ b/sparse_array/arrayn/arrayn.go @@ -0,0 +1,126 @@ +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 + + dim int + data *Node // []*Node +} + +func New() *ArrayN { + return NewWithCap(8, 8, 8) +} + +func NewWithCap(dims ...int) *ArrayN { + arr := &ArrayN{dim: 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]) + return arr +} + +func (arr *ArrayN) Values() []interface{} { + return nil +} + +func (arr *ArrayN) set(curDim int, curidx int, data **Node, parent *Node) (*Node, int) { + + sidx := arr.dim - curDim + + if *data == nil { + if parent != nil { + parent.size++ + } + if curDim > 1 { + *data = &Node{data: make([]*Node, arr.dims[sidx], arr.dims[sidx])} + } else { + *data = &Node{data: make([]interface{}, arr.dims[sidx], arr.dims[sidx])} + return *data, curidx + } + } + + if curDim == 1 { + return *data, curidx + } + + nidx := curidx % arr.product[sidx] + dimindex := curidx / arr.product[sidx] + cur := *data + return arr.set(curDim-1, nidx, &cur.data.([]*Node)[dimindex], cur) +} + +func (arr *ArrayN) get(curDim int, curidx int, data **Node) (*Node, int) { + sidx := arr.dim - curDim + + if *data == nil { + return nil, 0 + } + + if curDim == 1 { + return *data, curidx + } + + nidx := curidx % arr.product[sidx] + dimindex := curidx / arr.product[sidx] + cur := *data + return arr.get(curDim-1, nidx, &cur.data.([]*Node)[dimindex]) +} + +func (arr *ArrayN) Set(idx int, value interface{}) { + n, nidx := arr.set(arr.dim, idx, &arr.data, nil) + n.data.([]interface{})[nidx] = value +} + +func (arr *ArrayN) Get(idx int) (interface{}, bool) { + n, nidx := arr.get(arr.dim, 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, data **Node) (*Node, int) { + sidx := arr.dim - curDim + + if *data == nil { + return nil, 0 + } + + if curDim == 1 { + return *data, curidx + } + + nidx := curidx % arr.product[sidx] + dimindex := curidx / arr.product[sidx] + cur := *data + return arr.del(curDim-1, nidx, &cur.data.([]*Node)[dimindex]) +} + +func (arr *ArrayN) Del(idx int) (interface{}, bool) { + return nil, true +} diff --git a/sparse_array/arrayn/arrayn_test.go b/sparse_array/arrayn/arrayn_test.go new file mode 100644 index 0000000..cee2fd2 --- /dev/null +++ b/sparse_array/arrayn/arrayn_test.go @@ -0,0 +1,53 @@ +package arrayn + +import ( + "testing" + + "github.com/Pallinder/go-randomdata" +) + +func TestCase1(t *testing.T) { + arr := NewWithCap(3, 3, 3, 3) + for i := 0; i < 52; i++ { + arr.Set(i, i) + } + + t.Error(arr.Get(2)) + t.Error(arr.Get(1)) + t.Error(arr.Get(80)) +} + +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(10, 10, 10, 10000) + 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) + } + } + +}