数据结构与算法- 栈

231 阅读2分钟

这是我参与更文挑战的第12天,活动详情查看: 更文挑战

数据结构与算法- 栈

如何理解“栈”?

堆栈(Stack)就像数组,但功能有限。堆栈提供LIFO或后进先出。 最后推进的元素是即将被推出的第一个元素。(非常类似的数据结构,队列是FIFO,或先进先出。)

有一个生活中例子, 比如家里放的一骡盘子,我们放盘子的时候,都是从下往上面一个一个的放,取得时候,也是从上面往下面一个一个的取;不能从中间随意的抽取;后进者先出,先进者后出,这就是典型的的结构;

img

特性

从栈的操作特性上来看,栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。

思考

栈的这种数据结构相比数据和链表,栈带给我的只有限制,并没有任何的优势。直接使用数组或者链表不就好了吗?为什么还要用这个操作受限的栈呢?

事实上,从功能上来说,数据和链表确实可以替代栈。但你知道,特定的数据结构是对特定场景的抽象。而且数组和链表暴露了太多的操作的接口,操作的确实灵活自由,但使用时就比较不可控,自然也就更容易出错;

当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出,先进后出的特性,这时候我们就应该首选栈这种数据结构;

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
    }
}

image-20210613233515447.png

参考:

segmentfault.com/a/119000001…

www.jianshu.com/p/f76e7d9aa…

如何实现浏览器的前进和后退功能?