You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
2.4 KiB

9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
  1. package common
  2. import (
  3. "bytes"
  4. "container/heap"
  5. )
  6. /*
  7. Example usage:
  8. ```
  9. h := NewHeap()
  10. h.Push("msg1", 1)
  11. h.Push("msg3", 3)
  12. h.Push("msg2", 2)
  13. fmt.Println(h.Pop()) // msg1
  14. fmt.Println(h.Pop()) // msg2
  15. fmt.Println(h.Pop()) // msg3
  16. ```
  17. */
  18. type Heap struct {
  19. pq priorityQueue
  20. }
  21. func NewHeap() *Heap {
  22. return &Heap{pq: make([]*pqItem, 0)}
  23. }
  24. func (h *Heap) Len() int64 {
  25. return int64(len(h.pq))
  26. }
  27. func (h *Heap) Push(value interface{}, priority int) {
  28. heap.Push(&h.pq, &pqItem{value: value, priority: cmpInt(priority)})
  29. }
  30. func (h *Heap) PushBytes(value interface{}, priority []byte) {
  31. heap.Push(&h.pq, &pqItem{value: value, priority: cmpBytes(priority)})
  32. }
  33. func (h *Heap) PushComparable(value interface{}, priority Comparable) {
  34. heap.Push(&h.pq, &pqItem{value: value, priority: priority})
  35. }
  36. func (h *Heap) Peek() interface{} {
  37. if len(h.pq) == 0 {
  38. return nil
  39. }
  40. return h.pq[0].value
  41. }
  42. func (h *Heap) Update(value interface{}, priority Comparable) {
  43. h.pq.Update(h.pq[0], value, priority)
  44. }
  45. func (h *Heap) Pop() interface{} {
  46. item := heap.Pop(&h.pq).(*pqItem)
  47. return item.value
  48. }
  49. //-----------------------------------------------------------------------------
  50. // From: http://golang.org/pkg/container/heap/#example__priorityQueue
  51. type pqItem struct {
  52. value interface{}
  53. priority Comparable
  54. index int
  55. }
  56. type priorityQueue []*pqItem
  57. func (pq priorityQueue) Len() int { return len(pq) }
  58. func (pq priorityQueue) Less(i, j int) bool {
  59. return pq[i].priority.Less(pq[j].priority)
  60. }
  61. func (pq priorityQueue) Swap(i, j int) {
  62. pq[i], pq[j] = pq[j], pq[i]
  63. pq[i].index = i
  64. pq[j].index = j
  65. }
  66. func (pq *priorityQueue) Push(x interface{}) {
  67. n := len(*pq)
  68. item := x.(*pqItem)
  69. item.index = n
  70. *pq = append(*pq, item)
  71. }
  72. func (pq *priorityQueue) Pop() interface{} {
  73. old := *pq
  74. n := len(old)
  75. item := old[n-1]
  76. item.index = -1 // for safety
  77. *pq = old[0 : n-1]
  78. return item
  79. }
  80. func (pq *priorityQueue) Update(item *pqItem, value interface{}, priority Comparable) {
  81. item.value = value
  82. item.priority = priority
  83. heap.Fix(pq, item.index)
  84. }
  85. //--------------------------------------------------------------------------------
  86. // Comparable
  87. type Comparable interface {
  88. Less(o interface{}) bool
  89. }
  90. type cmpInt int
  91. func (i cmpInt) Less(o interface{}) bool {
  92. return int(i) < int(o.(cmpInt))
  93. }
  94. type cmpBytes []byte
  95. func (bz cmpBytes) Less(o interface{}) bool {
  96. return bytes.Compare([]byte(bz), []byte(o.(cmpBytes))) < 0
  97. }