完成堆, 还差hashset
This commit is contained in:
parent
42cd6ef9fa
commit
3bc9a99ca9
237
heap/array3.go
237
heap/array3.go
|
@ -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
|
||||
}
|
168
heap/heap.go
168
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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user