queue.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. // Copyright (c) 2013, Peter H. Froehlich. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license
  3. // that can be found in the LICENSE file.
  4. // Package queue implements a double-ended queue abstraction on
  5. // top of a slice/array. All operations are constant time except
  6. // for PushFront and PushBack which are amortized constant time.
  7. package queue
  8. import "fmt"
  9. // Queue represents a double-ended queue.
  10. // The zero value for Queue is an empty queue ready to use.
  11. type Queue struct {
  12. // PushBack writes to rep[back] and then increments
  13. // back; PushFront decrements front and then writes
  14. // to rep[front]; gotta love those invariants.
  15. rep []interface{}
  16. front, back, length int
  17. }
  18. // New returns an initialized empty queue.
  19. func New() *Queue {
  20. return new(Queue).Init()
  21. }
  22. // Init initializes or clears queue q.
  23. func (q *Queue) Init() *Queue {
  24. // start with a slice of length 2 even if that "wastes"
  25. // some memory; we do front/back arithmetic modulo the
  26. // length, so starting at 1 requires special cases
  27. q.rep = make([]interface{}, 2) // TODO: keep old slice/array? but what if it's huge?
  28. q.front, q.back, q.length = 0, 0, 0
  29. return q
  30. }
  31. // TODO: good idea? list.go does it but slows down every insertion...
  32. // I guess that's the price for allowing zero values to be useful?
  33. func (q *Queue) lazyInit() {
  34. if q.rep == nil {
  35. q.Init()
  36. }
  37. }
  38. // Len returns the number of elements of queue q.
  39. func (q *Queue) Len() int {
  40. return q.length
  41. }
  42. func (q *Queue) empty() bool {
  43. return q.length == 0
  44. }
  45. func (q *Queue) full() bool {
  46. return q.length == len(q.rep)
  47. }
  48. func (q *Queue) grow() {
  49. big := make([]interface{}, q.length*2)
  50. j := q.front
  51. for i := 0; i < q.length; i++ {
  52. big[i] = q.rep[j]
  53. q.inc(&j)
  54. }
  55. q.rep = big
  56. q.front = 0
  57. q.back = q.length
  58. }
  59. // TODO: leave this in or not?
  60. func (q *Queue) String() string {
  61. result := fmt.Sprintf("(f: %d b: %d l:%d c:%d)", q.front, q.back, q.length, len(q.rep))
  62. result = result + "["
  63. j := q.front
  64. for i := 0; i < q.length; i++ {
  65. result = result + fmt.Sprintf("[%v]", q.rep[j])
  66. q.inc(&j)
  67. }
  68. result = result + "]"
  69. return result
  70. }
  71. // TODO: convert these two back to proper functions? see ugliness in Back() below
  72. func (q *Queue) inc(i *int) {
  73. l := len(q.rep)
  74. *i = (*i+1+l) % l
  75. }
  76. func (q *Queue) dec(i *int) {
  77. l := len(q.rep)
  78. *i = (*i-1+l) % l
  79. }
  80. // TODO: I dislike the Go philosophy of avoiding panics at all
  81. // costs; Front/Back/Pop from an empty Queue SHOULD panic! at
  82. // least in my mind...
  83. // Front returns the first element of queue q or nil.
  84. func (q *Queue) Front() interface{} {
  85. if q.empty() { return nil }
  86. return q.rep[q.front]
  87. }
  88. // Back returns the last element of queue q or nil.
  89. func (q *Queue) Back() interface{} {
  90. if q.empty() { return nil }
  91. b := q.back
  92. q.dec(&b)
  93. return q.rep[b]
  94. }
  95. // PushFront inserts a new value v at the front of queue q.
  96. func (q *Queue) PushFront(v interface{}) {
  97. q.lazyInit() // TODO: keep?
  98. if q.full() { q.grow() }
  99. q.dec(&q.front)
  100. q.rep[q.front] = v
  101. q.length++
  102. }
  103. // PushBack inserts a new value v at the back of queue q.
  104. func (q *Queue) PushBack(v interface{}) {
  105. q.lazyInit() // TODO: keep?
  106. if q.full() { q.grow() }
  107. q.rep[q.back] = v
  108. q.inc(&q.back)
  109. q.length++
  110. }
  111. // PopFront removes and returns the first element of queue q or nil.
  112. func (q *Queue) PopFront() interface{} {
  113. if q.empty() { return nil }
  114. v := q.rep[q.front]
  115. q.rep[q.front] = nil // nice to GC?
  116. q.inc(&q.front)
  117. q.length--
  118. return v
  119. }
  120. // PopBack removes and returns the last element of queue q or nil.
  121. func (q *Queue) PopBack() interface{} {
  122. if q.empty() { return nil }
  123. q.dec(&q.back)
  124. v := q.rep[q.back]
  125. q.rep[q.back] = nil // nice to GC?
  126. q.length--
  127. return v
  128. }