Queue.swift 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. //
  2. // Queue.swift
  3. // Platform
  4. //
  5. // Created by Krunoslav Zaher on 3/21/15.
  6. // Copyright © 2015 Krunoslav Zaher. All rights reserved.
  7. //
  8. /**
  9. Data structure that represents queue.
  10. Complexity of `enqueue`, `dequeue` is O(1) when number of operations is
  11. averaged over N operations.
  12. Complexity of `peek` is O(1).
  13. */
  14. struct Queue<T>: Sequence {
  15. /// Type of generator.
  16. typealias Generator = AnyIterator<T>
  17. private let resizeFactor = 2
  18. private var storage: ContiguousArray<T?>
  19. private var innerCount = 0
  20. private var pushNextIndex = 0
  21. private let initialCapacity: Int
  22. /**
  23. Creates new queue.
  24. - parameter capacity: Capacity of newly created queue.
  25. */
  26. init(capacity: Int) {
  27. initialCapacity = capacity
  28. storage = ContiguousArray<T?>(repeating: nil, count: capacity)
  29. }
  30. private var dequeueIndex: Int {
  31. let index = pushNextIndex - count
  32. return index < 0 ? index + storage.count : index
  33. }
  34. /// - returns: Is queue empty.
  35. var isEmpty: Bool { count == 0 }
  36. /// - returns: Number of elements inside queue.
  37. var count: Int { innerCount }
  38. /// - returns: Element in front of a list of elements to `dequeue`.
  39. func peek() -> T {
  40. precondition(count > 0)
  41. return storage[dequeueIndex]!
  42. }
  43. mutating private func resizeTo(_ size: Int) {
  44. var newStorage = ContiguousArray<T?>(repeating: nil, count: size)
  45. let count = self.count
  46. let dequeueIndex = self.dequeueIndex
  47. let spaceToEndOfQueue = storage.count - dequeueIndex
  48. // first batch is from dequeue index to end of array
  49. let countElementsInFirstBatch = Swift.min(count, spaceToEndOfQueue)
  50. // second batch is wrapped from start of array to end of queue
  51. let numberOfElementsInSecondBatch = count - countElementsInFirstBatch
  52. newStorage[0 ..< countElementsInFirstBatch] = storage[dequeueIndex ..< (dequeueIndex + countElementsInFirstBatch)]
  53. newStorage[countElementsInFirstBatch ..< (countElementsInFirstBatch + numberOfElementsInSecondBatch)] = storage[0 ..< numberOfElementsInSecondBatch]
  54. self.innerCount = count
  55. pushNextIndex = count
  56. storage = newStorage
  57. }
  58. /// Enqueues `element`.
  59. ///
  60. /// - parameter element: Element to enqueue.
  61. mutating func enqueue(_ element: T) {
  62. if count == storage.count {
  63. resizeTo(Swift.max(storage.count, 1) * resizeFactor)
  64. }
  65. storage[pushNextIndex] = element
  66. pushNextIndex += 1
  67. innerCount += 1
  68. if pushNextIndex >= storage.count {
  69. pushNextIndex -= storage.count
  70. }
  71. }
  72. private mutating func dequeueElementOnly() -> T {
  73. precondition(count > 0)
  74. let index = dequeueIndex
  75. defer {
  76. storage[index] = nil
  77. innerCount -= 1
  78. }
  79. return storage[index]!
  80. }
  81. /// Dequeues element or throws an exception in case queue is empty.
  82. ///
  83. /// - returns: Dequeued element.
  84. mutating func dequeue() -> T? {
  85. if self.count == 0 {
  86. return nil
  87. }
  88. defer {
  89. let downsizeLimit = storage.count / (resizeFactor * resizeFactor)
  90. if count < downsizeLimit && downsizeLimit >= initialCapacity {
  91. resizeTo(storage.count / resizeFactor)
  92. }
  93. }
  94. return dequeueElementOnly()
  95. }
  96. /// - returns: Generator of contained elements.
  97. func makeIterator() -> AnyIterator<T> {
  98. var i = dequeueIndex
  99. var innerCount = count
  100. return AnyIterator {
  101. if innerCount == 0 {
  102. return nil
  103. }
  104. defer {
  105. innerCount -= 1
  106. i += 1
  107. }
  108. if i >= self.storage.count {
  109. i -= self.storage.count
  110. }
  111. return self.storage[i]
  112. }
  113. }
  114. }