From 3bc9a99ca972112dfbb6b76b6d672e18edc21a1d Mon Sep 17 00:00:00 2001 From: eson <474420502@qq.com> Date: Tue, 16 Apr 2019 07:09:32 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E5=A0=86,=20=E8=BF=98?= =?UTF-8?q?=E5=B7=AEhashset?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- heap/array3.go | 237 --------------------------------------------- heap/heap.go | 168 +++++++++++++++++--------------- heap/heap_test.go | 57 +++++------ lastack/lastack.go | 6 +- 4 files changed, 120 insertions(+), 348 deletions(-) delete mode 100644 heap/array3.go diff --git a/heap/array3.go b/heap/array3.go deleted file mode 100644 index 039f9c3..0000000 --- a/heap/array3.go +++ /dev/null @@ -1,237 +0,0 @@ -package heap - -type arrayN struct { - ysizes []int - xsizes [][]int - xyproduct int - zsize int - ysize int - xsize int - data [][][]interface{} - - cap int -} - -func newArray() *arrayN { - return newWithCap(8, 8, 8) -} - -func newWithCap(zsize, ysize, xsize int) *arrayN { - arr := &arrayN{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 *arrayN) 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 *arrayN) 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 *arrayN) Cap() int { - return arr.cap -} - -func (arr *arrayN) 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 *arrayN) 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 *arrayN) getOfSet(idx int, value interface{}) ([]interface{}, int) { - 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 - return xdata, xindex -} - -func (arr *arrayN) 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 *arrayN) get(idx int) ([]interface{}, int) { - zindex := idx / arr.xyproduct - nextsize := (idx % arr.xyproduct) - yindex := nextsize / arr.xsize - xindex := nextsize % arr.xsize - - xdata := arr.data[zindex][yindex] - return xdata, xindex -} - -func (arr *arrayN) 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/heap/heap.go b/heap/heap.go index 6342f76..f01ab07 100644 --- a/heap/heap.go +++ b/heap/heap.go @@ -6,45 +6,90 @@ import ( type Heap struct { size int - elements *arrayN + elements []interface{} Compare compare.Compare } func New(Compare compare.Compare) *Heap { h := &Heap{Compare: Compare} - h.elements = newWithCap(8, 8, 8) + h.elements = make([]interface{}, 16, 16) return h } +func (h *Heap) Size() int { + return h.size +} + func (h *Heap) Values() []interface{} { - return h.elements.Values()[0:h.size] + 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 h.size >= h.elements.Cap() { - h.elements.Grow(h.elements.zsize * 2) + if v == nil { + return } + h.grow() + curidx := h.size - curarray, curarrayidx := h.elements.getOfSet(curidx, v) - h.size++ - // up for curidx != 0 { - pidx := (curidx - 1) / 2 - parray, parrayidx := h.elements.get(pidx) - pvalue := parray[parrayidx] + pidx := (curidx - 1) >> 1 + pvalue := h.elements[pidx] if h.Compare(v, pvalue) > 0 { - curarray[curarrayidx], parray[parrayidx] = parray[parrayidx], curarray[curarrayidx] + h.elements[curidx] = pvalue curidx = pidx - curarray = parray - curarrayidx = parrayidx } 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) { @@ -53,88 +98,57 @@ func (h *Heap) Pop() (interface{}, bool) { return nil, false } + curidx := 0 + top := h.elements[curidx] h.size-- - curidx := 0 - curarray, curarrayidx := h.elements.get(curidx) - curvalue := curarray[curarrayidx] + h.slimming() + if h.size == 0 { - return curvalue, true + return top, true } - result := curvalue - - lastarray, lastarrayidx := h.elements.get(h.size) - curarray[curarrayidx] = lastarray[lastarrayidx] - curvalue = curarray[curarrayidx] - - var childidx, childarrayidx int - var childarray []interface{} - var childvalue interface{} + downvalue := h.elements[h.size] + var cidx, c1, c2 int + var cvalue1, cvalue2, cvalue interface{} // down - for curidx < h.size { + for { + cidx = curidx << 1 - var childidx1, childidx2, childarrayidx1, childarrayidx2 int - var childarray1, childarray2 []interface{} - var childvalue1, childvalue2 interface{} + c2 = cidx + 2 + if c2 < h.size { + cvalue2 = h.elements[c2] - movidx := curidx << 1 - childidx2 = movidx + 2 - if childidx2 < h.size { - childarray2, childarrayidx2 = h.elements.get(childidx2) - childvalue2 = childarray2[childarrayidx2] + c1 = cidx + 1 + cvalue1 = h.elements[c1] - childidx1 = curidx<<1 + 1 - childarray1, childarrayidx1 = h.elements.get(childidx1) - childvalue1 = childarray1[childarrayidx1] - - if h.Compare(childvalue1, childvalue2) >= 0 { - childvalue = childvalue1 - childidx = childidx1 - childarray = childarray1 - childarrayidx = childarrayidx1 + if h.Compare(cvalue1, cvalue2) >= 0 { + cidx = c1 + cvalue = cvalue1 } else { - childvalue = childvalue2 - childidx = childidx2 - childarray = childarray2 - childarrayidx = childarrayidx2 + cidx = c2 + cvalue = cvalue2 } - } else { - childidx1 = movidx + 1 - if childidx1 < h.size { - childarray1, childarrayidx1 = h.elements.get(childidx1) - childvalue1 = childarray1[childarrayidx1] - - childvalue = childvalue1 - childidx = childidx1 - childarray = childarray1 - childarrayidx = childarrayidx1 + c1 = cidx + 1 + if c1 < h.size { + cvalue1 = h.elements[c1] + cidx = c1 + cvalue = cvalue1 } else { break } + } - if h.Compare(curvalue, childvalue) < 0 { - curarray[curarrayidx] = childvalue - childarray[childarrayidx] = curvalue - curidx = childidx - curarray = childarray - curarrayidx = childarrayidx + if h.Compare(cvalue, downvalue) > 0 { + h.elements[curidx] = cvalue + curidx = cidx } else { break } } - - return result, true - -} - -func (h *Heap) shiftdown(v interface{}) { - -} - -func (h *Heap) shiftup(v interface{}) { - + h.elements[curidx] = downvalue + return top, true } diff --git a/heap/heap_test.go b/heap/heap_test.go index 00064d1..cd70d26 100644 --- a/heap/heap_test.go +++ b/heap/heap_test.go @@ -52,12 +52,12 @@ func TestPush(t *testing.T) { func TestPop(t *testing.T) { - for i := 0; i < 500000; i++ { + for i := 0; i < 200000; i++ { h := New(Int) // m := make(map[int]int) gods := binaryheap.NewWithIntComparator() - for c := 0; c < 20; c++ { + for c := 0; c < 40; c++ { v := randomdata.Number(0, 100) // if _, ok := m[v]; !ok { h.Push(v) @@ -92,20 +92,18 @@ func TestPop(t *testing.T) { func BenchmarkPush(b *testing.B) { - var i int - b.N = 500000000 + l := loadTestData() - 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++ { + b.ResetTimer() + execCount := 50 + b.N = len(l) * execCount + + for c := 0; c < execCount; c++ { + b.StopTimer() h := New(Int) - for i = 0; i < b.N/10; i++ { - // arr.Set(l[i], i) - h.Push(l[i]) + b.StartTimer() + for _, v := range l { + h.Push(v) } } } @@ -117,7 +115,7 @@ func BenchmarkPop(b *testing.B) { l := loadTestData() b.ResetTimer() - execCount := 10 + execCount := 20 b.N = len(l) * execCount for c := 0; c < execCount; c++ { @@ -130,7 +128,6 @@ func BenchmarkPop(b *testing.B) { h.Pop() } } - } func BenchmarkGodsPop(b *testing.B) { @@ -140,7 +137,7 @@ func BenchmarkGodsPop(b *testing.B) { l := loadTestData() b.ResetTimer() - execCount := 10 + execCount := 20 b.N = len(l) * execCount for c := 0; c < execCount; c++ { @@ -156,21 +153,19 @@ func BenchmarkGodsPop(b *testing.B) { } -func BenchmarkGods(b *testing.B) { - var i int +func BenchmarkGodsPush(b *testing.B) { + l := loadTestData() - 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++ { - h := binaryheap.NewWithIntComparator() - for i = 0; i < b.N/10; i++ { - // arr.Set(l[i], i) - h.Push(l[i]) + 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) } } } diff --git a/lastack/lastack.go b/lastack/lastack.go index 6cc18c5..a0febff 100644 --- a/lastack/lastack.go +++ b/lastack/lastack.go @@ -26,10 +26,10 @@ func (as *Stack) grow() bool { as.cache = nil } else { var growsize int - if as.size <= 200 { - growsize = as.size * 2 + if as.size <= 256 { + growsize = as.size << 1 } else { - growsize = 200 + as.size/4 + growsize = 256 + as.size>>2 } grownode = &Node{elements: make([]interface{}, growsize, growsize), cur: -1} }