queue.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  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 int
  17. back int
  18. length int
  19. }
  20. // New returns an initialized empty queue.
  21. func New() *Queue {
  22. return new(Queue).Init()
  23. }
  24. // Init initializes or clears queue q.
  25. func (q *Queue) Init() *Queue {
  26. // start with a slice of length 2 even if that "wastes"
  27. // some memory; we do front/back arithmetic modulo the
  28. // length, so starting at 1 requires special cases
  29. q.rep = make([]interface{}, 2)
  30. // for some time I considered reusing the existing slice
  31. // if all a client does is re-initialize the queue; the
  32. // big problem with that is that the previous queue might
  33. // have been huge while the current queue doesn't grow
  34. // much at all; if that were to happen we'd hold on to a
  35. // huge chunk of memory for just a few elements and nobody
  36. // could do anything about it; so instead I decided to
  37. // just allocate a new slice and let the GC take care of
  38. // the previous one; seems a better tradeoff all around
  39. q.front, q.back, q.length = 0, 0, 0
  40. return q
  41. }
  42. // lazyInit lazily initializes a zero Queue value.
  43. //
  44. // I am mostly doing this because container/list does the same thing.
  45. // Personally I think it's a little wasteful because every single
  46. // PushFront/PushBack is going to pay the overhead of calling this.
  47. // But that's the price for making zero values useful immediately,
  48. // something Go apparently likes a lot.
  49. func (q *Queue) lazyInit() {
  50. if q.rep == nil {
  51. q.Init()
  52. }
  53. }
  54. // Len returns the number of elements of queue q.
  55. func (q *Queue) Len() int {
  56. return q.length
  57. }
  58. // empty returns true if the queue q has no elements.
  59. func (q *Queue) empty() bool {
  60. return q.length == 0
  61. }
  62. // full returns true if the queue q is at capacity.
  63. func (q *Queue) full() bool {
  64. return q.length == len(q.rep)
  65. }
  66. // grow doubles the size of queue q's underlying slice/array.
  67. func (q *Queue) grow() {
  68. big := make([]interface{}, q.length*2)
  69. j := q.front
  70. for i := 0; i < q.length; i++ {
  71. big[i] = q.rep[j]
  72. j = q.inc(j)
  73. }
  74. q.rep = big
  75. q.front = 0
  76. q.back = q.length
  77. }
  78. // TODO: leave this in or not?
  79. func (q *Queue) String() string {
  80. // result := fmt.Sprintf("(f: %d b: %d l:%d c:%d)", q.front, q.back, q.length, len(q.rep))
  81. result := ""
  82. result = result + "["
  83. j := q.front
  84. for i := 0; i < q.length; i++ {
  85. if i == q.length-1 {
  86. result = result + fmt.Sprintf("%v", q.rep[j])
  87. } else {
  88. result = result + fmt.Sprintf("%v, ", q.rep[j])
  89. }
  90. j = q.inc(j)
  91. }
  92. result = result + "]"
  93. return result
  94. }
  95. // inc returns the next integer position wrapping around queue q.
  96. func (q *Queue) inc(i int) int {
  97. l := len(q.rep)
  98. return (i + 1 + l) % l
  99. }
  100. // dec returns the previous integer position wrapping around queue q.
  101. func (q *Queue) dec(i int) int {
  102. l := len(q.rep)
  103. return (i - 1 + l) % l
  104. }
  105. // Front returns the first element of queue q or nil.
  106. func (q *Queue) Front() interface{} {
  107. if q.empty() {
  108. return nil
  109. }
  110. return q.rep[q.front]
  111. }
  112. // Back returns the last element of queue q or nil.
  113. func (q *Queue) Back() interface{} {
  114. if q.empty() {
  115. return nil
  116. }
  117. return q.rep[q.dec(q.back)]
  118. }
  119. // PushFront inserts a new value v at the front of queue q.
  120. func (q *Queue) PushFront(v interface{}) {
  121. q.lazyInit() // TODO: keep?
  122. if q.full() {
  123. q.grow()
  124. }
  125. q.front = q.dec(q.front)
  126. q.rep[q.front] = v
  127. q.length++
  128. }
  129. // PushBack inserts a new value v at the back of queue q.
  130. func (q *Queue) PushBack(v interface{}) {
  131. q.lazyInit() // TODO: keep?
  132. if q.full() {
  133. q.grow()
  134. }
  135. q.rep[q.back] = v
  136. q.back = q.inc(q.back)
  137. q.length++
  138. }
  139. // PopFront removes and returns the first element of queue q or nil.
  140. func (q *Queue) PopFront() interface{} {
  141. if q.empty() {
  142. return nil
  143. }
  144. v := q.rep[q.front]
  145. q.rep[q.front] = nil // nice to GC?
  146. q.front = q.inc(q.front)
  147. q.length--
  148. return v
  149. }
  150. // PopBack removes and returns the last element of queue q or nil.
  151. func (q *Queue) PopBack() interface{} {
  152. if q.empty() {
  153. return nil
  154. }
  155. q.back = q.dec(q.back)
  156. v := q.rep[q.back]
  157. q.rep[q.back] = nil // nice to GC?
  158. q.length--
  159. return v
  160. }