这是我参与更文挑战的第12天,活动详情查看: 更文挑战
数据结构与算法- 栈
如何理解“栈”?
堆栈(Stack)就像数组,但功能有限。堆栈提供LIFO或后进先出。 最后推进的元素是即将被推出的第一个元素。(非常类似的数据结构,队列是FIFO,或先进先出。)
有一个生活中例子, 比如家里放的一骡盘子,我们放盘子的时候,都是从下往上面一个一个的放,取得时候,也是从上面往下面一个一个的取;不能从中间随意的抽取;后进者先出,先进者后出,这就是典型的栈的结构;
特性
从栈的操作特性上来看,栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。
思考
栈的这种数据结构相比数据和链表,栈带给我的只有限制,并没有任何的优势。直接使用数组或者链表不就好了吗?为什么还要用这个操作受限的栈呢?
事实上,从功能上来说,数据和链表确实可以替代栈。但你知道,特定的数据结构是对特定场景的抽象。而且数组和链表暴露了太多的操作的接口,操作的确实灵活自由,但使用时就比较不可控,自然也就更容易出错;
当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出,先进后出的特性,这时候我们就应该首选栈这种数据结构;
Swift 实现一个栈结构
还是使用我们老朋友:Playground
通过数组数据结构实现:push,pop和peek方法
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
}
}
extension Stack: CustomStringConvertible {
var description: String {
let topDivider = "-----Stack---\n"
let bottomDivider = "\n----------\n"
// 复习下之前的尾随闭包简化写法
var list = array.map{ e in
return "\(e)"
}
var list2 = array.map{"\($0)"}
let stackElements = list2.reversed().joined(separator: "\n")
return topDivider + stackElements + bottomDivider
}
}
var bookStack = Stack<String>()
bookStack.push("西游记")
bookStack.push("三国演义")
bookStack.push("红楼梦")
bookStack.push("金瓶梅")
print(bookStack)
/**
-----Stack---
金瓶梅
红楼梦
三国演义
西游记
----------
*/
extension Stack {
var isEmpty: Bool {
return array.isEmpty
}
var count : Int {
return array.count
}
}