priorityqueue.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. * Public Domain Software
  3. *
  4. * I (Matthias Ladkau) am the author of the source code in this file.
  5. * I have placed the source code in this file in the public domain.
  6. *
  7. * For further information see: http://creativecommons.org/publicdomain/zero/1.0/
  8. */
  9. package sortutil
  10. import (
  11. "bytes"
  12. "container/heap"
  13. "fmt"
  14. )
  15. /*
  16. PriorityQueue is like a regular queue where each element has a priority. Items with
  17. higher priority are served first. Items with the same priority are returned in the
  18. order they were added. Priority 0 is the highest priority with the priority
  19. decreasing as the priority number increases.
  20. It is possible to set a minimum priority function on the PriorityQueue object.
  21. The function returns the current minimum priority level which should be returned
  22. by the queue. If the current available priority is lower than this then len()
  23. will return 0 and pop will return nil. If the function returns a negative value
  24. then the value is ignored.
  25. */
  26. type PriorityQueue struct {
  27. heap *priorityQueueHeap // Heap which holds the values
  28. orderCounter int
  29. MinPriority func() int // Function returning the minimum priority
  30. }
  31. /*
  32. NewPriorityQueue creates a new priority queue.
  33. */
  34. func NewPriorityQueue() *PriorityQueue {
  35. pqheap := make(priorityQueueHeap, 0)
  36. pq := &PriorityQueue{&pqheap, 0, func() int { return -1 }}
  37. heap.Init(pq.heap)
  38. return pq
  39. }
  40. /*
  41. Clear clears the current queue contents.
  42. */
  43. func (pq *PriorityQueue) Clear() {
  44. pqheap := make(priorityQueueHeap, 0)
  45. pq.heap = &pqheap
  46. pq.orderCounter = 0
  47. heap.Init(pq.heap)
  48. }
  49. /*
  50. CurrentPriority returns the priority of the next item.
  51. */
  52. func (pq *PriorityQueue) CurrentPriority() int {
  53. if len(*pq.heap) == 0 {
  54. return 0
  55. }
  56. return pq.heap.Peek().(*pqItem).priority
  57. }
  58. /*
  59. Push adds a new element to the queue.
  60. */
  61. func (pq *PriorityQueue) Push(value interface{}, priority int) {
  62. // Highest priority is 0 we can't go higher
  63. if priority < 0 {
  64. priority = 0
  65. }
  66. heap.Push(pq.heap, &pqItem{value, priority, pq.orderCounter, 0})
  67. pq.orderCounter++
  68. }
  69. /*
  70. Peek returns the next item of the queue but does not remove it.
  71. */
  72. func (pq *PriorityQueue) Peek() interface{} {
  73. minPriority := pq.MinPriority()
  74. if len(*pq.heap) == 0 || (minPriority > 0 && pq.heap.Peek().(*pqItem).priority > minPriority) {
  75. return nil
  76. }
  77. return pq.heap.Peek().(*pqItem).value
  78. }
  79. /*
  80. Pop remove the next element from the queue and returns it.
  81. */
  82. func (pq *PriorityQueue) Pop() interface{} {
  83. minPriority := pq.MinPriority()
  84. if len(*pq.heap) == 0 || (minPriority > 0 && pq.heap.Peek().(*pqItem).priority > minPriority) {
  85. return nil
  86. }
  87. return heap.Pop(pq.heap).(*pqItem).value
  88. }
  89. /*
  90. Size returns the current queue size.
  91. */
  92. func (pq *PriorityQueue) Size() int {
  93. minPriority := pq.MinPriority()
  94. if len(*pq.heap) == 0 || (minPriority > 0 && pq.heap.Peek().(*pqItem).priority > minPriority) {
  95. return 0
  96. }
  97. return len(*pq.heap)
  98. }
  99. /*
  100. SizeCurrentPriority returns the queue size of all elements of the highest priority.
  101. */
  102. func (pq *PriorityQueue) SizeCurrentPriority() int {
  103. minPriority := pq.MinPriority()
  104. if len(*pq.heap) == 0 || (minPriority > 0 && pq.heap.Peek().(*pqItem).priority > minPriority) {
  105. return 0
  106. }
  107. higestPriority := pq.heap.Peek().(*pqItem).priority
  108. counter := 0
  109. for _, item := range *pq.heap {
  110. if item.priority == higestPriority {
  111. counter++
  112. }
  113. }
  114. return counter
  115. }
  116. /*
  117. String returns a string representation of the queue.
  118. */
  119. func (pq *PriorityQueue) String() string {
  120. var ret bytes.Buffer
  121. ret.WriteString("[ ")
  122. for _, item := range *pq.heap {
  123. ret.WriteString(fmt.Sprintf("%v (%v) ", item.value, item.priority))
  124. }
  125. ret.WriteString("]")
  126. return ret.String()
  127. }
  128. // Internal datastructures
  129. // =======================
  130. /*
  131. pqItem models an item in the priority queue.
  132. */
  133. type pqItem struct {
  134. value interface{} // Value which is held in the queue
  135. priority int // Priority of the item
  136. order int // Order of adding
  137. index int // Item index in the heap (required by heap).
  138. }
  139. /*
  140. priorityQueueHeap implements the heap.Interface and is the datastructure which
  141. actually holds items.
  142. */
  143. type priorityQueueHeap []*pqItem
  144. func (pq priorityQueueHeap) Len() int { return len(pq) }
  145. func (pq priorityQueueHeap) Less(i, j int) bool {
  146. if pq[i].priority != pq[j].priority {
  147. return pq[i].priority < pq[j].priority
  148. }
  149. return pq[i].order < pq[j].order
  150. }
  151. func (pq priorityQueueHeap) Swap(i, j int) {
  152. pq[i], pq[j] = pq[j], pq[i]
  153. pq[i].index = i
  154. pq[j].index = j
  155. }
  156. /*
  157. Push adds an item to the queue.
  158. */
  159. func (pq *priorityQueueHeap) Push(x interface{}) {
  160. n := len(*pq)
  161. item := x.(*pqItem)
  162. item.index = n
  163. *pq = append(*pq, item)
  164. }
  165. /*
  166. Pop removes an item from the queue.
  167. */
  168. func (pq *priorityQueueHeap) Pop() interface{} {
  169. old := *pq
  170. n := len(old)
  171. item := old[n-1]
  172. item.index = -1
  173. *pq = old[0 : n-1]
  174. return item
  175. }
  176. /*
  177. Peek returns the next item but does not remove it from the queue.
  178. */
  179. func (pq *priorityQueueHeap) Peek() interface{} {
  180. q := *pq
  181. return q[0]
  182. }