Swift 5.3 数据结构——队列 Queue

队列 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

  1. 什么是ring buffer(circular buffer)
    一种环形数据结构,其长度是固定的,进出规则是FIFO先进先出,如果空间被填满了,之后写入的数据,会覆盖掉之前的数据。
  2. 这是一个栗子
    一个长度为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就被无情的覆盖掉了。
  3. 总结一下
    如果是读取操作,里面的数据就不断变少,直到为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

你可能感兴趣的:(Swift 5.3 数据结构——队列 Queue)