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}
 		}