概念
- 棧和數組差多,但是只有一些有限的功能。你只能 push 一個元素到棧頂,pop 移除棧頂的元素,peek 查看棧頂的元素
- 棧的順序是后進先出
- 按設計來說,棧不允許你查看內容。只有 peek 方法允許你查看棧頂
棧的實現
struct Stack {
fileprivate var array: [String] = []
}
Push
mutating func push(_ element: String) {
array.append(element)
}
- 注意這里是將元素添加到數組末尾,不是插入到開始位置。因為插入元素是一個 O(n) 復雜度的操作,這個操作會讓數組中現存的元素全部移動內存位置,append 不會
Pop
mutating func pop() -> String? {
return array.popLast()
}
Peek
func peek() -> String? {
return array.last
}
- peek 和 pop 類似,唯一的區別是去除了 mutating,因為 peek 不急改變 array
CustomStringConvertible
extension Stack: CustomStringConvertible {
var description: String {
let topDivider = "---Stack---\n"
let bottomDivider = "\n-----------\n"
let stackElements = array.reversed().joined(separator: "\n")
return topDivider + stackElements + bottomDivider
}
}
- 這里我們通過遵循 CustomStringConvertible 協議,這里協議中只有一個 description 屬性需要實現,通過更改這個屬性的 get 方法,可以改變 print 輸出的信息
var rwBookStack = Stack()
rwBookStack.push("3D Games by Tutorials")
rwBookStack.push("tvOS Apprentice")
rwBookStack.push("iOS Apprentice")
rwBookStack.push("Swift Apprentice")
print(rwBookStack)
---Stack---
Swift Apprentice
iOS Apprentice
tvOS Apprentice
3D Games by Tutorials
-----------
泛型
以上棧的實現我們只能傳入字符串,我們通過泛型來讓棧可以傳入任何類型
struct Stack<Element> {
fileprivate var array: [Element] = []
mutating func push(_ element: Element) {
array.append(element)
}
mutating func pop() -> Element? {
return array.popLast()
}
func peek() -> Element? {
return array.last
}
}
然后修改 description 屬性中的代碼
// 先將元素都轉為字符串類型,因為 joined 方法必須元素和傳入的參數類型一致
let stackElements = array.map { "\($0)" }.reversed().joined(separator: "\n")