TODO: PQ finish task

This commit is contained in:
eson 2019-02-01 03:57:40 +08:00
parent b2d62bb55a
commit 6e253bd2d3
2 changed files with 58 additions and 38 deletions

View File

@ -10,8 +10,7 @@ type PriorityQueue struct {
datas []interface{} datas []interface{}
size int size int
comparator utils.Comparator comparator utils.Comparator
isLeftSorted bool isSorted bool
isRightSorted bool
} }
// NewWithInt compare use int // NewWithInt compare use int
@ -54,6 +53,26 @@ func (pq *PriorityQueue) reMakeMemory() {
} }
func (pq *PriorityQueue) search(v interface{}) int {
left := pq.left
right := pq.right
for left < right-1 {
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 {
left = mid
} else {
right = mid
}
}
if pq.comparator(v, pq.datas[left]) > 0 {
return left + 1
} else {
return left
}
}
func (pq *PriorityQueue) Push(v interface{}) { func (pq *PriorityQueue) Push(v interface{}) {
if pq.size == 0 { if pq.size == 0 {
@ -65,46 +84,51 @@ func (pq *PriorityQueue) Push(v interface{}) {
} else { } else {
if pq.comparator(v, pq.datas[pq.mid]) > 0 { // if pq.comparator(v, pq.datas[pq.mid]) > 0 {
// if pq.right >= len(pq.datas) {
// // 重建 datas
// pq.reMakeMemory()
// }
// pq.datas[pq.right] = v
// pq.right++
// } else {
// if pq.left-1 < 0 {
// // 重建 datas
// pq.reMakeMemory()
// }
// pq.left--
// pq.datas[pq.left] = v
// }
idx := pq.search(v)
if idx > pq.mid {
if pq.right >= len(pq.datas) { if pq.right >= len(pq.datas) {
// 重建 datas
pq.reMakeMemory() pq.reMakeMemory()
} }
pq.datas[pq.right] = v }
pq.right++
if pq.isRightSorted {
pq.isRightSorted = false
} }
} else {
if pq.left-1 < 0 {
// 重建 datas
pq.reMakeMemory()
}
pq.left--
pq.datas[pq.left] = v
if pq.isLeftSorted {
pq.isLeftSorted = false
}
}
}
pq.size++ pq.size++
if pq.isSorted {
pq.isSorted = false
}
} }
func (pq *PriorityQueue) PopTop() (interface{}, bool) { // func (pq *PriorityQueue) PopTop() (interface{}, bool) {
return v, isok // return v, isok
} // }
func (pq *PriorityQueue) PopBottom() (interface{}, bool) { // func (pq *PriorityQueue) PopBottom() (interface{}, bool) {
return v, isok // return v, isok
} // }
func (pq *PriorityQueue) Top() (interface{}, bool) { func (pq *PriorityQueue) Top() (interface{}, bool) {
return pq.Get(0) return pq.Get(0)
@ -124,14 +148,9 @@ 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.isLeftSorted { if !pq.isSorted {
utils.Sort(values[0:pq.size/2], pq.comparator) utils.Sort(values, pq.comparator)
pq.isLeftSorted = true pq.isSorted = true
}
if !pq.isRightSorted {
utils.Sort(values[pq.size/2:], pq.comparator)
pq.isRightSorted = true
} }
return values return values

View File

@ -19,6 +19,7 @@ func TestPriorityQueue(t *testing.T) {
t.Error(p.Values()) t.Error(p.Values())
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))
@ -31,7 +32,7 @@ func BenchmarkPriorityQueue10(b *testing.B) {
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%10 == 0 { if i%100 == 0 {
p.Values() p.Values()
} }
} }