128 lines
2.2 KiB
Go
128 lines
2.2 KiB
Go
package plist
|
||
|
||
import (
|
||
"log"
|
||
"strings"
|
||
|
||
"github.com/davecgh/go-spew/spew"
|
||
"github.com/emirpasic/gods/trees/avltree"
|
||
"github.com/emirpasic/gods/utils"
|
||
)
|
||
|
||
// PriorityQueue 优先队列 适合数据量不大, 加索引
|
||
type PriorityQueue struct {
|
||
avl *avltree.Tree
|
||
size int
|
||
comparator utils.Comparator
|
||
splitlimit int
|
||
}
|
||
|
||
func (pq *PriorityQueue) String() string {
|
||
|
||
content := ""
|
||
|
||
iter := pq.avl.Iterator()
|
||
iter.End()
|
||
|
||
for iter.Prev() {
|
||
pl := iter.Value().(*PriorityList)
|
||
|
||
cur := pl.head
|
||
for cur != nil {
|
||
content += spew.Sprint(cur.value) + "-"
|
||
cur = cur.next
|
||
}
|
||
content = strings.TrimRight(content, "-")
|
||
content += " ~ "
|
||
}
|
||
|
||
return content
|
||
}
|
||
|
||
func NewWithIntComparator() *PriorityQueue {
|
||
pq := new(PriorityQueue)
|
||
pq.comparator = func(v1, v2 interface{}) int {
|
||
if v1.(int) > v2.(int) {
|
||
return 1
|
||
} else if v1.(int) < v2.(int) {
|
||
return -1
|
||
}
|
||
return 0
|
||
}
|
||
pq.avl = avltree.NewWith(pq.comparator)
|
||
pq.splitlimit = 8
|
||
pq.size = 0
|
||
return pq
|
||
}
|
||
|
||
func (pq *PriorityQueue) Push(value interface{}) {
|
||
var pl *PriorityList
|
||
pq.size++
|
||
|
||
defer func() {
|
||
if pl.size >= pq.splitlimit {
|
||
moveIndex := pl.size / 2
|
||
cur := pl.head
|
||
for i := 1; i < moveIndex; i++ {
|
||
cur = cur.next
|
||
}
|
||
log.Println("pq:", pq.String())
|
||
temp := cur.next
|
||
cur.next = nil
|
||
|
||
plsp := &PriorityList{}
|
||
plsp.head = temp
|
||
plsp.size = pl.size - moveIndex
|
||
|
||
pl.size = moveIndex
|
||
|
||
pq.avl.Put(plsp.head.value, plsp)
|
||
log.Println("list:", pl.head.value, pl.String())
|
||
log.Println("list:", plsp.head.value, plsp.String())
|
||
log.Println("values:", pq.avl.Values())
|
||
log.Println("pq:", pq.String(), "\n----------")
|
||
|
||
}
|
||
}()
|
||
|
||
floor, ok := pq.avl.Floor(value)
|
||
if ok {
|
||
|
||
pl = floor.Value.(*PriorityList)
|
||
cur := pl.head
|
||
pl.size++
|
||
|
||
if pq.comparator(value, cur.value) > 0 {
|
||
|
||
temp := pl.head
|
||
pl.head = &Node{value: value}
|
||
pl.head.next = temp
|
||
|
||
return
|
||
}
|
||
|
||
for cur.next != nil {
|
||
if pq.comparator(value, cur.next.value) >= 0 {
|
||
temp := cur.next
|
||
cur.next = &Node{value: value}
|
||
cur.next.next = temp
|
||
return
|
||
}
|
||
cur = cur.next
|
||
}
|
||
// next == nil
|
||
cur.next = &Node{value: value}
|
||
return
|
||
|
||
}
|
||
|
||
pl = &PriorityList{}
|
||
pl.head = &Node{value: value}
|
||
pl.size++
|
||
|
||
pq.avl.Put(pl.head.value, pl)
|
||
|
||
return
|
||
|
||
}
|