deque.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // CookieJar - A contestant's algorithm toolbox
  2. // Copyright (c) 2013 Peter Szilagyi. All rights reserved.
  3. //
  4. // CookieJar is dual licensed: use of this source code is governed by a BSD
  5. // license that can be found in the LICENSE file. Alternatively, the CookieJar
  6. // toolbox may be used in accordance with the terms and conditions contained
  7. // in a signed written agreement between you and the author(s).
  8. // Package deque implements a double ended queue supporting arbitrary types
  9. // (even a mixture).
  10. //
  11. // Internally it uses a dynamically growing circular slice of blocks, resulting
  12. // in faster resizes than a simple dynamic array/slice would allow, yet less gc
  13. // overhead.
  14. package deque
  15. // The size of a block of data
  16. const blockSize = 4096
  17. // Double ended queue data structure.
  18. type Deque struct {
  19. leftIdx int
  20. leftOff int
  21. rightIdx int
  22. rightOff int
  23. blocks [][]interface{}
  24. left []interface{}
  25. right []interface{}
  26. }
  27. // Creates a new, empty deque.
  28. func New() *Deque {
  29. result := new(Deque)
  30. result.blocks = [][]interface{}{make([]interface{}, blockSize)}
  31. result.right = result.blocks[0]
  32. result.left = result.blocks[0]
  33. return result
  34. }
  35. // Pushes a new element into the queue from the right, expanding it if necessary.
  36. func (d *Deque) PushRight(data interface{}) {
  37. d.right[d.rightOff] = data
  38. d.rightOff++
  39. if d.rightOff == blockSize {
  40. d.rightOff = 0
  41. d.rightIdx = (d.rightIdx + 1) % len(d.blocks)
  42. // If we wrapped over to the left, insert a new block and update indices
  43. if d.rightIdx == d.leftIdx {
  44. buffer := make([][]interface{}, len(d.blocks)+1)
  45. copy(buffer[:d.rightIdx], d.blocks[:d.rightIdx])
  46. buffer[d.rightIdx] = make([]interface{}, blockSize)
  47. copy(buffer[d.rightIdx+1:], d.blocks[d.rightIdx:])
  48. d.blocks = buffer
  49. d.leftIdx++
  50. d.left = d.blocks[d.leftIdx]
  51. }
  52. d.right = d.blocks[d.rightIdx]
  53. }
  54. }
  55. // Pops out an element from the queue from the right. Note, no bounds checking are done.
  56. func (d *Deque) PopRight() (res interface{}) {
  57. d.rightOff--
  58. if d.rightOff < 0 {
  59. d.rightOff = blockSize - 1
  60. d.rightIdx = (d.rightIdx - 1 + len(d.blocks)) % len(d.blocks)
  61. d.right = d.blocks[d.rightIdx]
  62. }
  63. res, d.right[d.rightOff] = d.right[d.rightOff], nil
  64. return
  65. }
  66. // Returns the rightmost element from the deque. No bounds are checked.
  67. func (d *Deque) Right() interface{} {
  68. if d.rightOff > 0 {
  69. return d.right[d.rightOff-1]
  70. } else {
  71. return d.blocks[(d.rightIdx-1+len(d.blocks))%len(d.blocks)][blockSize-1]
  72. }
  73. }
  74. // Pushes a new element into the queue from the left, expanding it if necessary.
  75. func (d *Deque) PushLeft(data interface{}) {
  76. d.leftOff--
  77. if d.leftOff < 0 {
  78. d.leftOff = blockSize - 1
  79. d.leftIdx = (d.leftIdx - 1 + len(d.blocks)) % len(d.blocks)
  80. // If we wrapped over to the right, insert a new block and update indices
  81. if d.leftIdx == d.rightIdx {
  82. d.leftIdx++
  83. buffer := make([][]interface{}, len(d.blocks)+1)
  84. copy(buffer[:d.leftIdx], d.blocks[:d.leftIdx])
  85. buffer[d.leftIdx] = make([]interface{}, blockSize)
  86. copy(buffer[d.leftIdx+1:], d.blocks[d.leftIdx:])
  87. d.blocks = buffer
  88. }
  89. d.left = d.blocks[d.leftIdx]
  90. }
  91. d.left[d.leftOff] = data
  92. }
  93. // Pops out an element from the queue from the left. Note, no bounds checking are done.
  94. func (d *Deque) PopLeft() (res interface{}) {
  95. res, d.left[d.leftOff] = d.left[d.leftOff], nil
  96. d.leftOff++
  97. if d.leftOff == blockSize {
  98. d.leftOff = 0
  99. d.leftIdx = (d.leftIdx + 1) % len(d.blocks)
  100. d.left = d.blocks[d.leftIdx]
  101. }
  102. return
  103. }
  104. // Returns the leftmost element from the deque. No bounds are checked.
  105. func (d *Deque) Left() interface{} {
  106. return d.left[d.leftOff]
  107. }
  108. // Checks whether the queue is empty.
  109. func (d *Deque) Empty() bool {
  110. return d.leftIdx == d.rightIdx && d.leftOff == d.rightOff
  111. }
  112. // Returns the number of elements in the queue.
  113. func (d *Deque) Size() int {
  114. if d.rightIdx > d.leftIdx {
  115. return (d.rightIdx-d.leftIdx)*blockSize - d.leftOff + d.rightOff
  116. } else if d.rightIdx < d.leftIdx {
  117. return (len(d.blocks)-d.leftIdx+d.rightIdx)*blockSize - d.leftOff + d.rightOff
  118. } else {
  119. return d.rightOff - d.leftOff
  120. }
  121. }
  122. // Clears out the contents of the queue.
  123. func (d *Deque) Reset() {
  124. *d = *New()
  125. }