Queue.swift 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 _count = 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 {
  36. return count == 0
  37. }
  38. /// - returns: Number of elements inside queue.
  39. var count: Int {
  40. return _count
  41. }
  42. /// - returns: Element in front of a list of elements to `dequeue`.
  43. func peek() -> T {
  44. precondition(count > 0)
  45. return _storage[dequeueIndex]!
  46. }
  47. mutating private func resizeTo(_ size: Int) {
  48. var newStorage = ContiguousArray<T?>(repeating: nil, count: size)
  49. let count = _count
  50. let dequeueIndex = self.dequeueIndex
  51. let spaceToEndOfQueue = _storage.count - dequeueIndex
  52. // first batch is from dequeue index to end of array
  53. let countElementsInFirstBatch = Swift.min(count, spaceToEndOfQueue)
  54. // second batch is wrapped from start of array to end of queue
  55. let numberOfElementsInSecondBatch = count - countElementsInFirstBatch
  56. newStorage[0 ..< countElementsInFirstBatch] = _storage[dequeueIndex ..< (dequeueIndex + countElementsInFirstBatch)]
  57. newStorage[countElementsInFirstBatch ..< (countElementsInFirstBatch + numberOfElementsInSecondBatch)] = _storage[0 ..< numberOfElementsInSecondBatch]
  58. _count = count
  59. _pushNextIndex = count
  60. _storage = newStorage
  61. }
  62. /// Enqueues `element`.
  63. ///
  64. /// - parameter element: Element to enqueue.
  65. mutating func enqueue(_ element: T) {
  66. if count == _storage.count {
  67. resizeTo(Swift.max(_storage.count, 1) * _resizeFactor)
  68. }
  69. _storage[_pushNextIndex] = element
  70. _pushNextIndex += 1
  71. _count += 1
  72. if _pushNextIndex >= _storage.count {
  73. _pushNextIndex -= _storage.count
  74. }
  75. }
  76. private mutating func dequeueElementOnly() -> T {
  77. precondition(count > 0)
  78. let index = dequeueIndex
  79. defer {
  80. _storage[index] = nil
  81. _count -= 1
  82. }
  83. return _storage[index]!
  84. }
  85. /// Dequeues element or throws an exception in case queue is empty.
  86. ///
  87. /// - returns: Dequeued element.
  88. mutating func dequeue() -> T? {
  89. if self.count == 0 {
  90. return nil
  91. }
  92. defer {
  93. let downsizeLimit = _storage.count / (_resizeFactor * _resizeFactor)
  94. if _count < downsizeLimit && downsizeLimit >= _initialCapacity {
  95. resizeTo(_storage.count / _resizeFactor)
  96. }
  97. }
  98. return dequeueElementOnly()
  99. }
  100. /// - returns: Generator of contained elements.
  101. func makeIterator() -> AnyIterator<T> {
  102. var i = dequeueIndex
  103. var count = _count
  104. return AnyIterator {
  105. if count == 0 {
  106. return nil
  107. }
  108. defer {
  109. count -= 1
  110. i += 1
  111. }
  112. if i >= self._storage.count {
  113. i -= self._storage.count
  114. }
  115. return self._storage[i]
  116. }
  117. }
  118. }