队列 Queue
队列是一种特殊的线性表,原则就是先进先出,只能从头取数据,从尾部插入数据。
1. 先定义一个队列协议
添加入队enqueue
和出队dequeue
方法,队列头部peek
属性。
队列是具体实现方法有很多种
public protocol Queue {
associatedtype Element
mutating func enqueue(_ element: Element) -> Bool
mutating func dequeue() -> Element?
var isEmpty: Bool { get }
var peek: Element? { get }
}
2. 使用数组实现一个队列
public struct ArrayQueue: Queue {
private var array: [Element] = []
public init() {}
public var isEmpty: Bool {
array.isEmpty
}
public var peek: Element? {
array.first
}
@discardableResult
public mutating func enqueue(_ element: Element) -> Bool {
array.append(element)
return true
}
public mutating func dequeue() -> Element? {
isEmpty ? nil : array.removeFirst()
}
}
3.使用链表实现一个队列
public class LinkedListQueue: Queue {
private var list = DoublyLinkedList()
public init() {}
public var isEmpty: Bool {
list.isEmpty
}
public var peek: Element? {
list.first?.value
}
@discardableResult
public func enqueue(_ element: Element) -> Bool {
list.append(element)
return true
}
public func dequeue() -> Element? {
guard !list.isEmpty, let element = list.first else {
return nil
}
return list.remove(element)
}
}
4.使用Ring Buffer实现一个队列
对Ring Buffer不熟悉的可以向看
public struct RingBufferQueue: Queue {
private var ringBuffer: RingBuffer
public init(count: Int) {
ringBuffer = RingBuffer(count: count)
}
public var isEmpty: Bool {
ringBuffer.isEmpty
}
public var peek: Element? {
ringBuffer.first
}
@discardableResult
public mutating func enqueue(_ element: Element) -> Bool {
return ringBuffer.write(element)
}
@discardableResult
public mutating func dequeue() -> Element? {
ringBuffer.read()
}
}
5.使用双栈实现一个队列
public struct StackQueue: Queue {
private var leftStack: [Element] = []
private var rightStack: [Element] = []
public init() {}
public var isEmpty: Bool {
leftStack.isEmpty && rightStack.isEmpty
}
public var peek: Element? {
!leftStack.isEmpty ? leftStack.last : rightStack.first
}
@discardableResult
public mutating func enqueue(_ element: Element) -> Bool {
rightStack.append(element)
return true
}
@discardableResult
public mutating func dequeue() -> Element? {
if leftStack.isEmpty {
leftStack = rightStack.reversed()
rightStack.removeAll()
}
return leftStack.popLast()
}
}
github仓库地址 https://github.com/SunZhiC/DataStructuresInSwift
Ring Buffer
- 什么是ring buffer(circular buffer)
一种环形数据结构,其长度是固定的,进出规则是FIFO先进先出,如果空间被填满了,之后写入的数据,会覆盖掉之前的数据。 - 这是一个栗子
一个长度为7的Ring Buffer
写入一个元素1,输出:1
写入2和3,输出: 1 2 3
再写入4 5 6 7, 输出:1 2 3 4 5 6 7
此时ring buffer已经被充满,取出一个数据,那么取出来的数据是 1,剩下的数据是2 3 4 5 6 7
再写入A和B,因为剩余空间为1,需要顶掉一个元素,才能成功添加2个元素,所以要完成写入A和B的操作,先添加A,输出是2 3 4 5 6 7 A,再添加B ,输出是3 4 5 6 7 A B ,元素2就被无情的覆盖掉了。 - 总结一下
如果是读取操作,里面的数据就不断变少,直到为0。
如果是写入操作,当元素个数等于规定的长度的时候,队列前面的元素就会被顶掉。
References
What is Circular Buffer, by wikipedia
Data Structures & Algorithms in Swift by Matthijs Hollemans.
https://github.com/apple/swift-algorithms
https://github.com/raywenderlich/swift-algorithm-club