Swift算法俱樂部:Swift隊列數據結構(Queue)

翻譯自raywenderlich網站iOS教程Swift Algorithm Club系列算法

準備開始編程

隊列(Queue)是一個列表,您只能在後面插入新項目並從前面刪除項目。 這可確保入隊的第一個元素也是首先出隊的元素。 先到先出
在許多算法中,咱們但願在某個時間點將項目添加到臨時列表中,而後在之後再次將它們從列表中拉出。 添加和刪除這些項目的順序很是重要。swift

隊列提供先進先出或先入先出的順序。 首先插入的元素也是第一個出來的元素(和堆棧(Stack)很是相似,是LIFO或後進先出。)segmentfault

這是一個栗子
理解隊列的最簡單方法是看看它是如何使用的。數據結構

想象一下你有一個隊列。 如下是你如何入選一個數字:app

queue.enqueue(10)

隊列如今是[10]。 而後,繼續將下一個號碼添加到隊列中:工具

queue.enqueue(3)

隊列如今是[10,3]。 繼續添加:學習

queue.enqueue(57)

隊列如今是[10,3,57]。 咱們能夠將隊列中的第一個元素從隊列中拉出:測試

queue.dequeue()

將返回10,由於這是插入的第一個數字。 隊列如今將是[3,57]。 每一個項目都向上移動一個地方。網站

queue.dequeue()

這將返回3.下一個出列將返回57,依此類推。 若是隊列爲空,則出隊將返回零。

實現隊列
在本節中,將實現一個存儲Int值的簡單通用隊列。
建立一個新的playground,添加以下代碼:

public struct Queue {
    
}

playground還包含LinkedList的代碼(能夠經過轉到查看 Project Navigators Show Project Navigator並打開Sources LinkedList來看到這一點。

入隊(Enqueue)

隊列須要入隊方法。 咱們使用項目中包含的LinkedList實現來實現隊列。 在花括號之間添加如下內容:

// 1
fileprivate var list = LinkedList<Int>()

// 2
public mutating func enqueue(_ element: Int) {
    list.append(element)
}
  1. 添加了一個fileprivate LinkedList變量,用於將這些項目存儲在隊列中。
  2. 已經添加了一個方法來排列項目。 這個方法會改變底層的LinkedList,因此明確地指定了在方法前加上mutating關鍵字。

出列(Dequeue)

隊列也須要一個出隊方法。

// 1
public mutating func dequeque() -> Int? {
    // 2
    guard !list.isEmpty, let element = list.first else { return nil}
    
    list.remove(element)
    
    return element.value
}
  1. 添加一個返回隊列中第一個項目的出隊方法。 返回類型能夠爲空來處理隊列爲空。
  2. 使用guard語句處理隊列爲空。 若是這個隊列是空的,那麼guard將會進入else塊。

查看(Peek)

隊列還須要一個peek方法,它在隊列的開始處返回該項目而不刪除它。

public func peek() -> Int? {
  return list.first?.value
}

IsEmpty

隊列能夠是空的。 添加一個isEmpty屬性,該屬性將返回基於LinkedList的值:

public var isEmpty: Bool {
    return list.isEmpty
}

打印隊列

讓咱們試試新隊列。 在隊列實現下面,將如下內容寫入playground中:

var queue = Queue()
queue.enqueue(10)
queue.enqueue(3)
queue.enqueue(57)

定義隊列後,嘗試將隊列打印到控制檯:

print(queue)

輸出以下:

Queue(list: [10, 3, 57])

這輸出的樣式不是很好。 要顯示更可讀的輸出字符串,可使隊列採用CustomStringConvertable協議。 爲此,請在Queue類的實現下方添加如下內容:

// 1
extension Queue: CustomStringConvertible {
    // 2
    public var description: String {
        // 3
        return list.description
    }
}
  1. 聲明Queue類的擴展,讓它遵循CustomStringConvertible協議。 該協議指望使用字符串類型實現帶名稱描述的計算屬性。
  2. 聲明瞭description屬性。 這是一個計算屬性,它是一個返回String的只讀屬性。
  3. 返回基於LinkedList的描述。

如今控制檯的輸出編程以下樣式:

[10, 3, 57]

Swift通用隊列實現
此時,咱們已經實現了一個存儲Int值的通用隊列,並提供了在Queue類中查看,排隊和出列項目的功能。
在本節中,咱們使用泛型從隊列中抽象出類型需求。

將Queue類的實現更新爲如下內容:

// 1
public struct Queue<T> {
    // 2
    fileprivate var list = LinkedList<T>()
    
    // 3
    public mutating func enqueue(_ element: T) {
        list.append(element)
    }
    
    // 4
    public mutating func dequeque() -> T? {

        guard !list.isEmpty, let element = list.first else { return nil}
        
        list.remove(element)
        
        return element.value
    }
    // 5
    public func peek() -> T? {
        return list.first?.value
    }
    
    public var isEmpty: Bool {
        return list.isEmpty
    }
}

修正測試代碼以下:

var queue = Queue<Int>()
queue.enqueue(10)
queue.enqueue(3)
queue.enqueue(57)
print(queue)

還能夠嘗試使用不一樣類型的Queue:

var queue2 = Queue<String>()
queue2.enqueue("mad")
queue2.enqueue("lad")
if let first = queue2.dequeque() {
    print(first)
}
print(queue2)

以上是本人在raywenderlich學習時爲方便本身,用翻譯工具翻譯以後作的一個記錄。

本系列其餘文章:
Swift算法俱樂部:Swift棧(Stack)數據結構

相關文章
相關標籤/搜索