本篇文章主要內容: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)
}
}
複製代碼