queue.go 4.8 KB

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