123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- //
- // Queue.swift
- // Platform
- //
- // Created by Krunoslav Zaher on 3/21/15.
- // Copyright © 2015 Krunoslav Zaher. All rights reserved.
- //
- /**
- Data structure that represents queue.
- Complexity of `enqueue`, `dequeue` is O(1) when number of operations is
- averaged over N operations.
- Complexity of `peek` is O(1).
- */
- struct Queue<T>: Sequence {
- /// Type of generator.
- typealias Generator = AnyIterator<T>
- private let _resizeFactor = 2
-
- private var _storage: ContiguousArray<T?>
- private var _count = 0
- private var _pushNextIndex = 0
- private let _initialCapacity: Int
- /**
- Creates new queue.
-
- - parameter capacity: Capacity of newly created queue.
- */
- init(capacity: Int) {
- _initialCapacity = capacity
- _storage = ContiguousArray<T?>(repeating: nil, count: capacity)
- }
-
- private var dequeueIndex: Int {
- let index = _pushNextIndex - count
- return index < 0 ? index + _storage.count : index
- }
-
- /// - returns: Is queue empty.
- var isEmpty: Bool {
- return count == 0
- }
-
- /// - returns: Number of elements inside queue.
- var count: Int {
- return _count
- }
-
- /// - returns: Element in front of a list of elements to `dequeue`.
- func peek() -> T {
- precondition(count > 0)
-
- return _storage[dequeueIndex]!
- }
-
- mutating private func resizeTo(_ size: Int) {
- var newStorage = ContiguousArray<T?>(repeating: nil, count: size)
-
- let count = _count
-
- let dequeueIndex = self.dequeueIndex
- let spaceToEndOfQueue = _storage.count - dequeueIndex
-
- // first batch is from dequeue index to end of array
- let countElementsInFirstBatch = Swift.min(count, spaceToEndOfQueue)
- // second batch is wrapped from start of array to end of queue
- let numberOfElementsInSecondBatch = count - countElementsInFirstBatch
-
- newStorage[0 ..< countElementsInFirstBatch] = _storage[dequeueIndex ..< (dequeueIndex + countElementsInFirstBatch)]
- newStorage[countElementsInFirstBatch ..< (countElementsInFirstBatch + numberOfElementsInSecondBatch)] = _storage[0 ..< numberOfElementsInSecondBatch]
-
- _count = count
- _pushNextIndex = count
- _storage = newStorage
- }
-
- /// Enqueues `element`.
- ///
- /// - parameter element: Element to enqueue.
- mutating func enqueue(_ element: T) {
- if count == _storage.count {
- resizeTo(Swift.max(_storage.count, 1) * _resizeFactor)
- }
-
- _storage[_pushNextIndex] = element
- _pushNextIndex += 1
- _count += 1
-
- if _pushNextIndex >= _storage.count {
- _pushNextIndex -= _storage.count
- }
- }
-
- private mutating func dequeueElementOnly() -> T {
- precondition(count > 0)
-
- let index = dequeueIndex
- defer {
- _storage[index] = nil
- _count -= 1
- }
- return _storage[index]!
- }
- /// Dequeues element or throws an exception in case queue is empty.
- ///
- /// - returns: Dequeued element.
- mutating func dequeue() -> T? {
- if self.count == 0 {
- return nil
- }
- defer {
- let downsizeLimit = _storage.count / (_resizeFactor * _resizeFactor)
- if _count < downsizeLimit && downsizeLimit >= _initialCapacity {
- resizeTo(_storage.count / _resizeFactor)
- }
- }
- return dequeueElementOnly()
- }
-
- /// - returns: Generator of contained elements.
- func makeIterator() -> AnyIterator<T> {
- var i = dequeueIndex
- var count = _count
- return AnyIterator {
- if count == 0 {
- return nil
- }
- defer {
- count -= 1
- i += 1
- }
- if i >= self._storage.count {
- i -= self._storage.count
- }
- return self._storage[i]
- }
- }
- }
|