Swift 數據結構學習:棧與隊列

本篇文章主要內容:node

  • 棧與隊列的基本概念
  • 棧與隊列的基本結構
  • 棧與隊列的互相實現

概念

  • 棧(stack)是限定僅在表尾進行插入和刪除操做的線性表。bash

  • 咱們把容許插入和刪除的一端稱爲棧頂(top),另外一端稱爲棧底(bottom),不含任何數據元素的棧稱爲空棧。棧又稱爲後進先出(LastIn First Out)的線性表,簡稱LIFO結構。app

結構

對棧來講,通常咱們只須要關注:push, pop, isEmpty, peek, size 等操做。ui

順序存儲結構:spa

class Stack {
    // 是否爲空
    var isEmpty: Bool {
        return stack.isEmpty
    }
    
    // 棧的大小
    var size: Int {
        return stack.count
    }
    
    // 棧頂元素
    var peek: Int? {
        return stack.last
    }
    
    // 入棧
    func push(_ value: Int) {
        stack.append(value)
    }
    
    // 出棧
    func pop() -> Int? {
        return stack.popLast()
    }
    
    private var stack: [Int] = []
}
複製代碼

鏈式存儲結構:指針

class Node {
    var value: Int?
    var next: Node?
    
    init(_ value: Int?) {
        self.value = value
        self.next = nil
    }
}

class Stack_Link {
    private var head: Node?   // 指向棧頂元素的指針
    
    var isEmpty: Bool {
        return head == nil
    }
    
    var size: Int {
        get {
            var count = 0
            
            var node = head?.next
            while node != nil {
                count += 1
                node = node?.next
            }
            return count
        }
    }
    
    var peek: Node? {
        return head?.next
    }
    
    func push(_ value: Int) {
        if head == nil {
            head = Node(nil)
        }
        
        let newNode = Node(value)
        
        let lastTop = head?.next
        
        newNode.next = lastTop
        head?.next = newNode
    }
    
    func pop() -> Node? {
        let top = head?.next
        head?.next = top?.next
        return top
    }
}
複製代碼

隊列

概念

  • 隊列(queue)是隻容許在一端進行插入操做,而在另外一端進行刪除操做的線性表。code

  • 隊列是一種先進先出(First In First Out)的線性表,簡稱FIFO。容許插入的一端稱爲隊尾,容許刪除的一端稱爲隊頭。隊列

結構

對隊列來講,通常咱們只須要關注:enterQueue, outQueue, isEmpty, peek, size 等操做。element

隊列順序存儲結構:rem

class Queue {
    // 是否爲空
    var isEmpty: Bool {
        return queue.isEmpty
    }
    
    // 隊列的大小
    var size: Int {
        return queue.count
    }
    
    // 隊頭元素
    var peek: Int? {
        return queue.last
    }
    
    // 入隊操做
    func enterQueue(_ value: Int) {
        queue.append(value)
    }
    
    // 出隊操做
    func outQueue() -> Int? {
        if let element = queue.first {
            queue.removeFirst()
            return element
        }
        return nil
    }
    
    private var queue: [Int] = []
}
複製代碼

隊列鏈式存儲結構:

class Node {
    var value: Int?
    var next: Node?
    
    init(_ value: Int?) {
        self.value = value
        self.next = nil
    }
}

class Queue_Link {
    private var head: Node? // 指向隊頭
    private var tail: Node? // 指向隊尾
    
    var isEmpty: Bool {
        return head == nil && tail == nil
    }
    
    var size: Int {
        get {
            var count = 0
            
            var node = head?.next
            while node != nil {
                count += 1
                node = node?.next
            }
            return count
        }
    }
    
    var peek: Node? {
        return head?.next
    }
    
    func enterQueue(_ value: Int) {
        let newNode = Node(value)
        if head == nil {
            head = Node(nil)
            tail = Node(nil)
            head?.next = newNode
            tail?.next = newNode
        } else {
            let lastTail = tail?.next
            
            lastTail?.next = newNode
            
            tail?.next = newNode
        }
    }
    
    func outQueue() -> Node? {
        let top = head?.next
        
        head?.next = top?.next
        
        return top
    }
}
複製代碼

互相實現

用棧實現隊列

思路: 由於棧的先進後出特性,須要完成先進先出的特色。咱們須要用到兩個棧,一個 enterStack,專門負責入隊的操做,另外一個 outStack,負責協助出隊。當入隊時,咱們將新元素 push 到 enterStack 中,出隊時分爲兩個步驟,先將 enterQueue 的元素 pop 出來,並將 pop 的元素加入到 outStack 中,此時 outStack 的棧頂元素就是最早入隊的元素。

代碼:

class ImplementQueueByStack {
    private var enterStack = Stack()
    private var outStack = Stack()
    
    var isEmpty: Bool {
        return enterStack.isEmpty && outStack.isEmpty
    }
    
    var size: Int {
        return enterStack.size + outStack.size
    }
    
    var peek: Int? {
        get {
            tab()
            return outStack.peek
        }
    }
    
    func enterQueue(_ value: Int) {
        enterStack.push(value)
    }
    
    func outQueue() -> Int? {
        tab()
        return outStack.pop()
    }
    
    // 將 enter 中的值,加入到 out 中
    private func tab() {
        if outStack.isEmpty {
            while !enterStack.isEmpty {
                outStack.push(enterStack.pop()!)
            }
        }
    }
}
複製代碼

用隊列實現棧

思路: 根據棧實現隊列的思路,這裏咱們也用兩個隊列來實現棧。一個 enterQueue,負責入棧,另外一個 outQueue 負責協助出棧。入棧時,將新的元素加入到 enterQueue中,出棧時,也分爲兩個步驟,先將 enterQueue 中的元素出隊至最後一個元素,並將全部出隊的元素加入到 outQueue 中,此時,enterQueue 中剩下的元素便是咱們須要出棧的元素。

代碼:

class ImplementStackByQueue {
    private var enterQueue = Queue()
    private var tempQueue = Queue()
    
    var isEmpty: Bool {
        return enterQueue.isEmpty && tempQueue.isEmpty
    }

    var size: Int {
        return enterQueue.size
    }

    var peek: Int? {
        get {
            tab()
            let peekElement = enterQueue.peek
            tempQueue.enterQueue(enterQueue.outQueue()!)
            swap()
            return peekElement
        }
    }
    
    func push(_ value: Int) {
        enterQueue.enterQueue(value)
    }
    
    func pop() -> Int? {
        tab()
        let popElement = enterQueue.outQueue()
        swap()
        return popElement
    }
    
    private func tab() {
        while enterQueue.size != 1 {
            tempQueue.enterQueue(enterQueue.outQueue()!)
        }
    }
    
    private func swap() {
        (enterQueue, tempQueue) = (tempQueue, enterQueue)
    }
}
複製代碼
相關文章
相關標籤/搜索