123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- /*
- * Public Domain Software
- *
- * I (Matthias Ladkau) am the author of the source code in this file.
- * I have placed the source code in this file in the public domain.
- *
- * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
- */
- package sortutil
- import (
- "bytes"
- "container/heap"
- "fmt"
- )
- /*
- PriorityQueue is like a regular queue where each element has a priority. Items with
- higher priority are served first. Items with the same priority are returned in the
- order they were added. Priority 0 is the highest priority with the priority
- decreasing as the priority number increases.
- It is possible to set a minimum priority function on the PriorityQueue object.
- The function returns the current minimum priority level which should be returned
- by the queue. If the current available priority is lower than this then len()
- will return 0 and pop will return nil. If the function returns a negative value
- then the value is ignored.
- */
- type PriorityQueue struct {
- heap *priorityQueueHeap // Heap which holds the values
- orderCounter int
- MinPriority func() int // Function returning the minimum priority
- }
- /*
- NewPriorityQueue creates a new priority queue.
- */
- func NewPriorityQueue() *PriorityQueue {
- pqheap := make(priorityQueueHeap, 0)
- pq := &PriorityQueue{&pqheap, 0, func() int { return -1 }}
- heap.Init(pq.heap)
- return pq
- }
- /*
- Clear clears the current queue contents.
- */
- func (pq *PriorityQueue) Clear() {
- pqheap := make(priorityQueueHeap, 0)
- pq.heap = &pqheap
- pq.orderCounter = 0
- heap.Init(pq.heap)
- }
- /*
- CurrentPriority returns the priority of the next item.
- */
- func (pq *PriorityQueue) CurrentPriority() int {
- if len(*pq.heap) == 0 {
- return 0
- }
- return pq.heap.Peek().(*pqItem).priority
- }
- /*
- Push adds a new element to the queue.
- */
- func (pq *PriorityQueue) Push(value interface{}, priority int) {
- // Highest priority is 0 we can't go higher
- if priority < 0 {
- priority = 0
- }
- heap.Push(pq.heap, &pqItem{value, priority, pq.orderCounter, 0})
- pq.orderCounter++
- }
- /*
- Peek returns the next item of the queue but does not remove it.
- */
- func (pq *PriorityQueue) Peek() interface{} {
- minPriority := pq.MinPriority()
- if len(*pq.heap) == 0 || (minPriority > 0 && pq.heap.Peek().(*pqItem).priority > minPriority) {
- return nil
- }
- return pq.heap.Peek().(*pqItem).value
- }
- /*
- Pop remove the next element from the queue and returns it.
- */
- func (pq *PriorityQueue) Pop() interface{} {
- minPriority := pq.MinPriority()
- if len(*pq.heap) == 0 || (minPriority > 0 && pq.heap.Peek().(*pqItem).priority > minPriority) {
- return nil
- }
- return heap.Pop(pq.heap).(*pqItem).value
- }
- /*
- Size returns the current queue size.
- */
- func (pq *PriorityQueue) Size() int {
- minPriority := pq.MinPriority()
- if len(*pq.heap) == 0 || (minPriority > 0 && pq.heap.Peek().(*pqItem).priority > minPriority) {
- return 0
- }
- return len(*pq.heap)
- }
- /*
- SizeCurrentPriority returns the queue size of all elements of the highest priority.
- */
- func (pq *PriorityQueue) SizeCurrentPriority() int {
- minPriority := pq.MinPriority()
- if len(*pq.heap) == 0 || (minPriority > 0 && pq.heap.Peek().(*pqItem).priority > minPriority) {
- return 0
- }
- higestPriority := pq.heap.Peek().(*pqItem).priority
- counter := 0
- for _, item := range *pq.heap {
- if item.priority == higestPriority {
- counter++
- }
- }
- return counter
- }
- /*
- String returns a string representation of the queue.
- */
- func (pq *PriorityQueue) String() string {
- var ret bytes.Buffer
- ret.WriteString("[ ")
- for _, item := range *pq.heap {
- ret.WriteString(fmt.Sprintf("%v (%v) ", item.value, item.priority))
- }
- ret.WriteString("]")
- return ret.String()
- }
- // Internal datastructures
- // =======================
- /*
- pqItem models an item in the priority queue.
- */
- type pqItem struct {
- value interface{} // Value which is held in the queue
- priority int // Priority of the item
- order int // Order of adding
- index int // Item index in the heap (required by heap).
- }
- /*
- priorityQueueHeap implements the heap.Interface and is the datastructure which
- actually holds items.
- */
- type priorityQueueHeap []*pqItem
- func (pq priorityQueueHeap) Len() int { return len(pq) }
- func (pq priorityQueueHeap) Less(i, j int) bool {
- if pq[i].priority != pq[j].priority {
- return pq[i].priority < pq[j].priority
- }
- return pq[i].order < pq[j].order
- }
- func (pq priorityQueueHeap) Swap(i, j int) {
- pq[i], pq[j] = pq[j], pq[i]
- pq[i].index = i
- pq[j].index = j
- }
- /*
- Push adds an item to the queue.
- */
- func (pq *priorityQueueHeap) Push(x interface{}) {
- n := len(*pq)
- item := x.(*pqItem)
- item.index = n
- *pq = append(*pq, item)
- }
- /*
- Pop removes an item from the queue.
- */
- func (pq *priorityQueueHeap) Pop() interface{} {
- old := *pq
- n := len(old)
- item := old[n-1]
- item.index = -1
- *pq = old[0 : n-1]
- return item
- }
- /*
- Peek returns the next item but does not remove it from the queue.
- */
- func (pq *priorityQueueHeap) Peek() interface{} {
- q := *pq
- return q[0]
- }
|