完成堆, 还差hashset

This commit is contained in:
eson 2019-04-16 07:09:32 +08:00
parent 42cd6ef9fa
commit 3bc9a99ca9
4 changed files with 120 additions and 348 deletions

View File

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

View File

@ -6,45 +6,90 @@ import (
type Heap struct { type Heap struct {
size int size int
elements *arrayN elements []interface{}
Compare compare.Compare Compare compare.Compare
} }
func New(Compare compare.Compare) *Heap { func New(Compare compare.Compare) *Heap {
h := &Heap{Compare: Compare} h := &Heap{Compare: Compare}
h.elements = newWithCap(8, 8, 8) h.elements = make([]interface{}, 16, 16)
return h return h
} }
func (h *Heap) Size() int {
return h.size
}
func (h *Heap) Values() []interface{} { 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{}) { func (h *Heap) Push(v interface{}) {
if v == nil {
if h.size >= h.elements.Cap() { return
h.elements.Grow(h.elements.zsize * 2)
} }
h.grow()
curidx := h.size curidx := h.size
curarray, curarrayidx := h.elements.getOfSet(curidx, v)
h.size++ h.size++
// up // up
for curidx != 0 { for curidx != 0 {
pidx := (curidx - 1) / 2 pidx := (curidx - 1) >> 1
parray, parrayidx := h.elements.get(pidx) pvalue := h.elements[pidx]
pvalue := parray[parrayidx]
if h.Compare(v, pvalue) > 0 { if h.Compare(v, pvalue) > 0 {
curarray[curarrayidx], parray[parrayidx] = parray[parrayidx], curarray[curarrayidx] h.elements[curidx] = pvalue
curidx = pidx curidx = pidx
curarray = parray
curarrayidx = parrayidx
} else { } else {
break 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) { func (h *Heap) Pop() (interface{}, bool) {
@ -53,88 +98,57 @@ func (h *Heap) Pop() (interface{}, bool) {
return nil, false return nil, false
} }
curidx := 0
top := h.elements[curidx]
h.size-- h.size--
curidx := 0 h.slimming()
curarray, curarrayidx := h.elements.get(curidx)
curvalue := curarray[curarrayidx]
if h.size == 0 { if h.size == 0 {
return curvalue, true return top, true
} }
result := curvalue downvalue := h.elements[h.size]
var cidx, c1, c2 int
lastarray, lastarrayidx := h.elements.get(h.size) var cvalue1, cvalue2, cvalue interface{}
curarray[curarrayidx] = lastarray[lastarrayidx]
curvalue = curarray[curarrayidx]
var childidx, childarrayidx int
var childarray []interface{}
var childvalue interface{}
// down // down
for curidx < h.size { for {
cidx = curidx << 1
var childidx1, childidx2, childarrayidx1, childarrayidx2 int c2 = cidx + 2
var childarray1, childarray2 []interface{} if c2 < h.size {
var childvalue1, childvalue2 interface{} cvalue2 = h.elements[c2]
movidx := curidx << 1 c1 = cidx + 1
childidx2 = movidx + 2 cvalue1 = h.elements[c1]
if childidx2 < h.size {
childarray2, childarrayidx2 = h.elements.get(childidx2)
childvalue2 = childarray2[childarrayidx2]
childidx1 = curidx<<1 + 1 if h.Compare(cvalue1, cvalue2) >= 0 {
childarray1, childarrayidx1 = h.elements.get(childidx1) cidx = c1
childvalue1 = childarray1[childarrayidx1] cvalue = cvalue1
if h.Compare(childvalue1, childvalue2) >= 0 {
childvalue = childvalue1
childidx = childidx1
childarray = childarray1
childarrayidx = childarrayidx1
} else { } else {
childvalue = childvalue2 cidx = c2
childidx = childidx2 cvalue = cvalue2
childarray = childarray2 }
childarrayidx = childarrayidx2 } else {
c1 = cidx + 1
if c1 < h.size {
cvalue1 = h.elements[c1]
cidx = c1
cvalue = cvalue1
} else {
break
} }
} else { }
childidx1 = movidx + 1 if h.Compare(cvalue, downvalue) > 0 {
if childidx1 < h.size { h.elements[curidx] = cvalue
childarray1, childarrayidx1 = h.elements.get(childidx1) curidx = cidx
childvalue1 = childarray1[childarrayidx1]
childvalue = childvalue1
childidx = childidx1
childarray = childarray1
childarrayidx = childarrayidx1
} else { } else {
break break
} }
} }
h.elements[curidx] = downvalue
if h.Compare(curvalue, childvalue) < 0 { return top, true
curarray[curarrayidx] = childvalue
childarray[childarrayidx] = curvalue
curidx = childidx
curarray = childarray
curarrayidx = childarrayidx
} else {
break
}
}
return result, true
}
func (h *Heap) shiftdown(v interface{}) {
}
func (h *Heap) shiftup(v interface{}) {
} }

View File

@ -52,12 +52,12 @@ func TestPush(t *testing.T) {
func TestPop(t *testing.T) { func TestPop(t *testing.T) {
for i := 0; i < 500000; i++ { for i := 0; i < 200000; i++ {
h := New(Int) h := New(Int)
// m := make(map[int]int) // m := make(map[int]int)
gods := binaryheap.NewWithIntComparator() gods := binaryheap.NewWithIntComparator()
for c := 0; c < 20; c++ { for c := 0; c < 40; c++ {
v := randomdata.Number(0, 100) v := randomdata.Number(0, 100)
// if _, ok := m[v]; !ok { // if _, ok := m[v]; !ok {
h.Push(v) h.Push(v)
@ -92,20 +92,18 @@ func TestPop(t *testing.T) {
func BenchmarkPush(b *testing.B) { func BenchmarkPush(b *testing.B) {
var i int l := loadTestData()
b.N = 500000000
b.ResetTimer()
execCount := 50
b.N = len(l) * execCount
for c := 0; c < execCount; c++ {
b.StopTimer() 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 := New(Int) h := New(Int)
for i = 0; i < b.N/10; i++ { b.StartTimer()
// arr.Set(l[i], i) for _, v := range l {
h.Push(l[i]) h.Push(v)
} }
} }
} }
@ -117,7 +115,7 @@ func BenchmarkPop(b *testing.B) {
l := loadTestData() l := loadTestData()
b.ResetTimer() b.ResetTimer()
execCount := 10 execCount := 20
b.N = len(l) * execCount b.N = len(l) * execCount
for c := 0; c < execCount; c++ { for c := 0; c < execCount; c++ {
@ -130,7 +128,6 @@ func BenchmarkPop(b *testing.B) {
h.Pop() h.Pop()
} }
} }
} }
func BenchmarkGodsPop(b *testing.B) { func BenchmarkGodsPop(b *testing.B) {
@ -140,7 +137,7 @@ func BenchmarkGodsPop(b *testing.B) {
l := loadTestData() l := loadTestData()
b.ResetTimer() b.ResetTimer()
execCount := 10 execCount := 20
b.N = len(l) * execCount b.N = len(l) * execCount
for c := 0; c < execCount; c++ { for c := 0; c < execCount; c++ {
@ -156,21 +153,19 @@ func BenchmarkGodsPop(b *testing.B) {
} }
func BenchmarkGods(b *testing.B) { func BenchmarkGodsPush(b *testing.B) {
var i int l := loadTestData()
b.N = 500000000 b.ResetTimer()
execCount := 50
b.N = len(l) * execCount
for c := 0; c < execCount; c++ {
b.StopTimer() b.StopTimer()
var l []int h := binaryheap.NewWith(Int)
for i := 0; i < b.N/10; i++ {
l = append(l, randomdata.Number(0, 65535))
}
b.StartTimer() b.StartTimer()
for c := 0; c < 10; c++ { for _, v := range l {
h := binaryheap.NewWithIntComparator() h.Push(v)
for i = 0; i < b.N/10; i++ {
// arr.Set(l[i], i)
h.Push(l[i])
} }
} }
} }

View File

@ -26,10 +26,10 @@ func (as *Stack) grow() bool {
as.cache = nil as.cache = nil
} else { } else {
var growsize int var growsize int
if as.size <= 200 { if as.size <= 256 {
growsize = as.size * 2 growsize = as.size << 1
} else { } else {
growsize = 200 + as.size/4 growsize = 256 + as.size>>2
} }
grownode = &Node{elements: make([]interface{}, growsize, growsize), cur: -1} grownode = &Node{elements: make([]interface{}, growsize, growsize), cur: -1}
} }