This commit is contained in:
huangsimin 2019-02-01 19:18:48 +08:00
parent 6e253bd2d3
commit 36d7f0208b
2 changed files with 96 additions and 28 deletions

View File

@ -1,6 +1,8 @@
package plist package plist
import ( import (
"log"
"github.com/emirpasic/gods/utils" "github.com/emirpasic/gods/utils"
) )
@ -43,30 +45,38 @@ func (pq *PriorityQueue) reMakeMemory() {
temp := make([]interface{}, capacity) temp := make([]interface{}, capacity)
mid := capacity / 2 mid := capacity / 2
left := mid - pq.size/2 left := mid - pq.size/2 - 1
copy(temp[left:], pq.datas[pq.left:pq.right]) x := pq.datas
copy(temp[left+1:], pq.datas[pq.left+1:pq.right])
pq.datas = temp pq.datas = temp
pq.left = left pq.left = left
pq.mid = mid pq.mid = mid
pq.right = pq.size + pq.left pq.right = pq.size + pq.left
log.Println(x, pq.datas, pq.left, pq.right)
} }
func (pq *PriorityQueue) search(v interface{}) int { func (pq *PriorityQueue) search(v interface{}) int {
left := pq.left // left := pq.left
right := pq.right // right := pq.right
data := pq.datas[pq.left+1 : pq.right]
left := 0
mid := 0
right := len(data)
for left < right-1 { for left < right-1 {
mid := (left + right) / 2 // 4 10 7 10 8 10 9 10 | 4 10 4 7 4 5 mid = (left + right) / 2 // 4 10 7 10 8 10 9 10 | 4 10 4 7 4 5
if pq.comparator(v, pq.datas[mid]) > 0 { if pq.comparator(v, data[mid]) > 0 {
left = mid left = mid
} else { } else {
right = mid right = mid
} }
} }
if pq.comparator(v, pq.datas[left]) > 0 { if pq.comparator(v, data[left]) > 0 {
return left + 1 return left + 1
} else { } else {
return left return left
@ -75,13 +85,27 @@ func (pq *PriorityQueue) search(v interface{}) int {
func (pq *PriorityQueue) Push(v interface{}) { func (pq *PriorityQueue) Push(v interface{}) {
defer func() {
if err := recover(); err != nil {
log.Println(pq.datas)
log.Println(pq.left, pq.right, pq.size)
log.Panic(err)
}
}()
if pq.size == 0 { if pq.size == 0 {
pq.mid = len(pq.datas) / 2 pq.mid = len(pq.datas) / 2
pq.left = pq.mid pq.left = pq.mid - 1
pq.right = pq.mid + 1 pq.right = pq.mid + 1
pq.datas[pq.mid] = v pq.datas[pq.mid] = v
log.Println(pq.datas)
log.Println(pq.left)
} else { } else {
// if pq.comparator(v, pq.datas[pq.mid]) > 0 { // if pq.comparator(v, pq.datas[pq.mid]) > 0 {
@ -102,22 +126,44 @@ func (pq *PriorityQueue) Push(v interface{}) {
// } // }
// pq.left-- // pq.left--
// pq.datas[pq.left] = v // pq.datas[pq.left] = v
// } // }
idx := pq.search(v) idx := pq.search(v)
if idx > pq.mid { log.Println("idx:", idx)
if idx > pq.size/2 {
if pq.right >= len(pq.datas) { if pq.right >= len(pq.datas) {
pq.reMakeMemory() pq.reMakeMemory()
} }
offset := pq.left + 1 + idx
copy(pq.datas[offset+1:], pq.datas[offset:pq.right])
pq.datas[offset] = v
pq.right++
// log.Println("right: ", pq.datas)
} else {
if pq.left < 0 {
// 重建 datas
pq.reMakeMemory()
}
offset := pq.left + 1 + idx
copy(pq.datas[pq.left:], pq.datas[pq.left+1:offset])
pq.datas[offset] = v
pq.left--
// log.Println("left: ", pq.datas)
} }
} }
pq.size++ pq.size++
if pq.isSorted { log.Println("push:", pq.datas)
pq.isSorted = false // if pq.isSorted {
} // pq.isSorted = false
// }
} }
// func (pq *PriorityQueue) PopTop() (interface{}, bool) { // func (pq *PriorityQueue) PopTop() (interface{}, bool) {
@ -146,12 +192,10 @@ func (pq *PriorityQueue) Get(index int) (interface{}, bool) {
} }
func (pq *PriorityQueue) Values() []interface{} { func (pq *PriorityQueue) Values() []interface{} {
values := pq.datas[pq.left:pq.right] // values := pq.datas[pq.left:pq.right]
// if !pq.isSorted {
if !pq.isSorted { // utils.Sort(values, pq.comparator)
utils.Sort(values, pq.comparator) // pq.isSorted = true
pq.isSorted = true // }
} return pq.datas[pq.left:pq.right]
return values
} }

View File

@ -3,6 +3,8 @@ package plist
import ( import (
"testing" "testing"
"github.com/davecgh/go-spew/spew"
"github.com/emirpasic/gods/utils" "github.com/emirpasic/gods/utils"
"github.com/Pallinder/go-randomdata" "github.com/Pallinder/go-randomdata"
@ -17,9 +19,30 @@ func TestPriorityQueue(t *testing.T) {
p.Push(randomdata.Number(0, 10000)) p.Push(randomdata.Number(0, 10000))
} }
t.Error(p.Values()) data := p.Values()
t.Error(data)
content := ""
last := 0
for i := 0; i < len(data); i++ {
if i == 0 {
content += "\n"
} else if i%5 == 0 {
content += spew.Sprintln(data[last:i])
last = i
}
}
content += spew.Sprintln(data[last:])
t.Error(content)
lleft := p.search(0)
lmid := p.search(5000)
lright := p.search(10000)
t.Error(lleft, lmid, lright)
t.Error(p.left+lleft, p.left+lmid, p.left+lright)
t.Error(p.datas, p.size, len(p.Values())) t.Error(p.datas, p.size, len(p.Values()))
t.Error(p.search(1000000))
for _, idx := range []int{5, 0, 21, 19} { for _, idx := range []int{5, 0, 21, 19} {
t.Error(p.Get(idx)) t.Error(p.Get(idx))
@ -27,17 +50,18 @@ func TestPriorityQueue(t *testing.T) {
} }
func BenchmarkPriorityQueue10(b *testing.B) { func BenchmarkPriorityQueue(b *testing.B) {
p := NewWithInt() p := NewWithInt()
// for i := 0; i < 100000; i++ {
// p.Push(randomdata.Number(0, 100000))
// // p.Values()
// }
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
p.Push(randomdata.Number(0, 100000)) p.Push(randomdata.Number(0, 100000))
if i%100 == 0 {
p.Values()
}
} }
// t.Error(p.String())
} }
func TestHeap(t *testing.T) { func TestHeap(t *testing.T) {