package plist import ( "github.com/davecgh/go-spew/spew" "github.com/emirpasic/gods/trees/avltree" "github.com/emirpasic/gods/utils" ) // PriorityQueue 优先队列 适合数据量不大, 加索引 type PriorityQueue struct { avlIndex *avltree.Tree indexlimit int node *Node size int comparator utils.Comparator } type Node struct { value interface{} // prev *Node next *Node } // NewWithInt compare use int func NewWithInt() *PriorityQueue { p := new(PriorityQueue) p.comparator = func(a, b interface{}) int { if a.(int) > b.(int) { return 1 } return -1 } p.indexlimit = 10 p.avlIndex = avltree.NewWith(p.comparator) return p } func (pq *PriorityQueue) String() string { content := "" for cur := pq.node; cur != nil; cur = cur.next { content += spew.Sprint(cur.value) + "-" } if content != "" { if content[len(content)-1] == '-' { content = content[:len(content)-1] } } idxContent := "" for idx := pq.index; idx != nil; idx = idx.next { idxContent += spew.Sprint(idx.node.value) + "(" + spew.Sprint(idx.nlen) + ")-" } return content + "\n" + idxContent } func (pq *PriorityQueue) findIndexStart(v interface{}) *Index { // find the node of index to start idx := pq.index for { if idx.next == nil { break } if pq.comparator(v, idx.next.node.value) > 0 { break } idx = idx.next } return idx } func (pq *PriorityQueue) Get(index int) (interface{}, bool) { if index < 0 || index >= pq.size { return nil, false } idx := pq.index movesize := index for { if movesize-idx.nlen <= 0 { break } else { movesize -= idx.nlen idx = idx.next } } cur := idx.node for movesize > 0 { movesize-- cur = cur.next } return cur.value, true } func (pq *PriorityQueue) Push(v interface{}) { node := new(Node) node.value = v pq.size++ if pq.node == nil { //创建索引 index := new(Index) index.nlen = 1 index.node = node pq.index = index pq.node = node return } // find the node of index to start idx := pq.findIndexStart(v) cur := idx.node if pq.comparator(v, pq.node.value) > 0 { pq.node = node node.next = cur pq.index.node = pq.node pq.index.nlen++ return } for i := 0; cur.next != nil; i++ { // 分裂和整理索引 if i >= pq.indexlimit { if idx.next != nil && idx.next.nlen < pq.indexlimit { idx.next.nlen += idx.nlen - pq.indexlimit idx.nlen = pq.indexlimit idx.next.node = cur idx = idx.next } else { index := new(Index) index.node = cur index.nlen = idx.nlen - pq.indexlimit index.next = idx.next idx.next = index idx.nlen = pq.indexlimit idx = index } i = 0 } if pq.comparator(v, cur.next.value) > 0 { temp := cur.next cur.next = node node.next = temp idx.nlen++ return } cur = cur.next } cur.next = node idx.nlen++ } 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] // }