tinyqueue.go 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package tinyqueue
  2. type Queue struct {
  3. length int
  4. data []Item
  5. }
  6. type Item interface {
  7. Less(Item) bool
  8. }
  9. func New(data []Item) *Queue {
  10. q := &Queue{}
  11. q.data = data
  12. q.length = len(data)
  13. if q.length > 0 {
  14. i := q.length >> 1
  15. for ; i >= 0; i-- {
  16. q.down(i)
  17. }
  18. }
  19. return q
  20. }
  21. func (q *Queue) Push(item Item) {
  22. q.data = append(q.data, item)
  23. q.length++
  24. q.up(q.length - 1)
  25. }
  26. func (q *Queue) Pop() Item {
  27. if q.length == 0 {
  28. return nil
  29. }
  30. top := q.data[0]
  31. q.length--
  32. if q.length > 0 {
  33. q.data[0] = q.data[q.length]
  34. q.down(0)
  35. }
  36. q.data = q.data[:len(q.data)-1]
  37. return top
  38. }
  39. func (q *Queue) Peek() Item {
  40. if q.length == 0 {
  41. return nil
  42. }
  43. return q.data[0]
  44. }
  45. func (q *Queue) Len() int {
  46. return q.length
  47. }
  48. func (q *Queue) down(pos int) {
  49. data := q.data
  50. halfLength := q.length >> 1
  51. item := data[pos]
  52. for pos < halfLength {
  53. left := (pos << 1) + 1
  54. right := left + 1
  55. best := data[left]
  56. if right < q.length && data[right].Less(best) {
  57. left = right
  58. best = data[right]
  59. }
  60. if !best.Less(item) {
  61. break
  62. }
  63. data[pos] = best
  64. pos = left
  65. }
  66. data[pos] = item
  67. }
  68. func (q *Queue) up(pos int) {
  69. data := q.data
  70. item := data[pos]
  71. for pos > 0 {
  72. parent := (pos - 1) >> 1
  73. current := data[parent]
  74. if !item.Less(current) {
  75. break
  76. }
  77. data[pos] = current
  78. pos = parent
  79. }
  80. data[pos] = item
  81. }