| 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]
 
- }
 
 
  |