202 lines
3.5 KiB
Go
202 lines
3.5 KiB
Go
package plist
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/emirpasic/gods/utils"
|
|
)
|
|
|
|
// PriorityQueue 优先队列 适合数据量不大, 加索引
|
|
type PriorityQueue struct {
|
|
left, right, mid int
|
|
datas []interface{}
|
|
size int
|
|
comparator utils.Comparator
|
|
isSorted bool
|
|
}
|
|
|
|
// NewWithInt compare use int
|
|
func NewWithInt() *PriorityQueue {
|
|
p := new(PriorityQueue)
|
|
p.datas = make([]interface{}, 8)
|
|
p.comparator = func(a, b interface{}) int {
|
|
if a.(int) > b.(int) {
|
|
return 1
|
|
}
|
|
return -1
|
|
}
|
|
return p
|
|
}
|
|
|
|
func (pq *PriorityQueue) reArrange() {
|
|
|
|
}
|
|
|
|
func (pq *PriorityQueue) reMakeMemory() {
|
|
|
|
var incSize int
|
|
if pq.size >= 1048 {
|
|
incSize = pq.size / 2
|
|
} else {
|
|
incSize = pq.size
|
|
}
|
|
|
|
capacity := pq.size + incSize
|
|
temp := make([]interface{}, capacity)
|
|
|
|
mid := capacity / 2
|
|
left := mid - pq.size/2 - 1
|
|
|
|
x := pq.datas
|
|
copy(temp[left+1:], pq.datas[pq.left+1:pq.right])
|
|
pq.datas = temp
|
|
pq.left = left
|
|
pq.mid = mid
|
|
pq.right = pq.size + pq.left
|
|
|
|
log.Println(x, pq.datas, pq.left, pq.right)
|
|
|
|
}
|
|
|
|
func (pq *PriorityQueue) search(v interface{}) int {
|
|
// left := pq.left
|
|
// right := pq.right
|
|
|
|
data := pq.datas[pq.left+1 : pq.right]
|
|
left := 0
|
|
mid := 0
|
|
right := len(data)
|
|
|
|
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, data[mid]) > 0 {
|
|
left = mid
|
|
} else {
|
|
right = mid
|
|
}
|
|
}
|
|
|
|
if pq.comparator(v, data[left]) > 0 {
|
|
return left + 1
|
|
} else {
|
|
return left
|
|
}
|
|
}
|
|
|
|
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 {
|
|
|
|
pq.mid = len(pq.datas) / 2
|
|
pq.left = pq.mid - 1
|
|
pq.right = pq.mid + 1
|
|
|
|
pq.datas[pq.mid] = v
|
|
|
|
log.Println(pq.datas)
|
|
log.Println(pq.left)
|
|
|
|
} else {
|
|
|
|
// 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)
|
|
log.Println("idx:", idx)
|
|
if idx > pq.size/2 {
|
|
|
|
if pq.right >= len(pq.datas) {
|
|
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++
|
|
log.Println("push:", pq.datas)
|
|
// if pq.isSorted {
|
|
// pq.isSorted = false
|
|
// }
|
|
}
|
|
|
|
// func (pq *PriorityQueue) PopTop() (interface{}, bool) {
|
|
|
|
// return v, isok
|
|
// }
|
|
|
|
// func (pq *PriorityQueue) PopBottom() (interface{}, bool) {
|
|
|
|
// return v, isok
|
|
// }
|
|
|
|
func (pq *PriorityQueue) Top() (interface{}, bool) {
|
|
return pq.Get(0)
|
|
}
|
|
|
|
func (pq *PriorityQueue) Bottom() (interface{}, bool) {
|
|
return pq.Get(pq.right - 1)
|
|
}
|
|
|
|
func (pq *PriorityQueue) Get(index int) (interface{}, bool) {
|
|
if index < pq.size {
|
|
return pq.Values()[index], true
|
|
}
|
|
return nil, false
|
|
}
|
|
|
|
func (pq *PriorityQueue) Values() []interface{} {
|
|
// values := pq.datas[pq.left:pq.right]
|
|
// if !pq.isSorted {
|
|
// utils.Sort(values, pq.comparator)
|
|
// pq.isSorted = true
|
|
// }
|
|
return pq.datas[pq.left:pq.right]
|
|
}
|