資料結構基礎--棧和佇列

目錄
- 基本性質
- 棧和佇列的基本操作
- 雙端佇列和優先順序佇列
- 深度優先遍歷(DFS)和廣度優先遍歷(BFS)
- 遞迴函式與系統函式棧
- 實現一個特殊的棧,在實現棧的基本功能的基礎上,再實現返回棧中最小元素的操作
- 如何儲存最小值
- 僅用棧結構實現佇列結構
- 如何保證棧結構能夠先進先出
- 何時進行傾倒操作
- 僅用佇列結構實現棧結
- 實現一個棧的逆序,不能申請額外的資料結構,只能使用棧本身的功能
- 移除棧底元素,並將其返回
- 將棧中的元素排序
基本性質
-
棧---先進後出
-
佇列---先進先出
-
棧和佇列通常都有陣列和連結串列兩種實現方式
陣列相對容易,連結串列需要進行一些指標操作
棧和佇列的基本操作
-
pop操作
彈出棧頂元素
-
top或peek操作
只訪問而不彈出棧頂元素
-
push操作
從棧頂壓入一個元素
-
size操作
返回當前棧中元素個數
對於佇列,push是在佇列頭部加入一個元素,pop是在尾部彈出一個元素。
棧和佇列的基本操作,時間複雜度都是O(1) 。
雙端佇列和優先順序佇列
-
雙端佇列
首尾都可以壓入和彈出元素
-
優先順序佇列
彈出時,根據元素的優先順序決定彈出的順序。
具體實現上為一個堆結構,而不是線性表結構。
深度優先遍歷(DFS)和廣度優先遍歷(BFS)
-
深度優先遍歷(前序遍歷)。使用棧的結構
先嚐試將左元素入棧,若棧頂元素為空則將棧頂推出然後嘗試遍歷右節點。直到棧為空則遍歷結束。

func preorderTraversal(root: TreeNode?) -> [Int] { var res = [Int]() var stack = [TreeNode]() //遍歷用的棧 var node = root//遍歷的根節點 while !stack.isEmpty || node != nil { if node != nil { res.append(node!.val)//將當前節點的值記錄 stack.append(node!) //將當前節點加入棧中 node = node!.left //嘗試遍歷當前節點的左節點 } else { node = stack.removeLast().right//將棧頂節點推出,並嘗試遍歷其父元素的右節點。 } } return res }
遍歷的結果為:1,2,4,5,3,6,7
-
廣度優先遍歷。使用佇列結構
從root節點開始依次入隊,當從佇列推出一個元素時,嘗試將其兩個子元素依次加入加入佇列。直到佇列為空遍歷結束。

遍歷的結果為:1,2,3,4,5,6,7
遞迴函式與系統函式棧
平時使用的遞迴函式實際上是有系統負責向系統函式棧中進行壓棧
遞迴過程可以看作是遞迴函式依次進入函式棧的處理過程
所有用遞迴函式可以做的過程,都可以用非遞迴的方式實現。
實現一個特殊的棧,在實現棧的基本功能的基礎上,再實現返回棧中最小元素的操作
【要求】
- pop、push、getMin操作的時間複雜度都是O(1)。
- 設計的棧型別可以使用現成的棧結構。
如何儲存最小值
需要兩個棧,StackData以及StackMin。StackData負責正常壓棧,StackMin負責記錄當前最小值。
當進行push操作時,當前元素與StackMin棧頂元素進行比較,將較小的數壓入StackMin。

當進行pop操作時,StackData以及StackMin同時進行pop。
當進行getmin操作時,由StackMin負責進行peek。
時間複雜度為O(1),額外空間複雜度為O(N)
僅用棧結構實現佇列結構
需要兩個棧結構實現。一個棧作為壓入棧(StackPush)負責承接push元素,一個棧作為彈出棧(StackPop)負責彈出pop元素。
-
如何保證棧結構能夠先進先出
通過將StackPush的資料倒入StackPop中,來將StackPush中資料的順序顛倒,保證先進先出。

這個傾倒操作需要有兩個注意的點:
-
StackPop棧
為空。 - 每次需要將
StackPush棧
所有的資料全部倒入StackPop棧
。
-
何時進行傾倒操作
當任何 StackPush
或者 StackPop棧
內的資料改變時,可以嘗試傾倒操作。
僅用佇列結構實現棧結
需要兩個佇列實現。
當進行pop操作時,將當前使用的CurrentQueue中元素推入輔助佇列HelpQueue,僅保留隊尾元素返回給使用者。
然後將CurrentQueue與HelpQueue的指標互換,保證push操作時,CurrentQueue始終為有內容的佇列。
實現一個棧的逆序,不能申請額外的資料結構,只能使用棧本身的功能
-
移除棧底元素,並將其返回
通過遞迴的方式,每層儲存相應的棧頂元素。獲取到棧底元素後再依次壓入棧中

/// 移除棧底元素,並將其返回 /// /// - Parameter stack: 棧 /// - Returns:棧底元素 func getLast(stack : Stack) -> Int { let value = stack.pop() //獲得當前棧頂元素 if stack.isEmpty() { //如果棧為空 return value //當前元素則為棧底元素 }else { let last = getLast(stack) stack.push(value) return last } }
將棧中的元素排序
【要求】
- 值允許申請一個棧
- 可以申請變數
- 不能申請額外的資料結構
原棧為stack,輔助棧為help。
從stack棧中pop出來的元素計作current
若current小於help棧頂元素,則直接壓入棧中。
若current大於help棧頂元素,則將help棧頂推出並壓入stack。
重複,直到stack中元素為0。然後將help倒回給stack

參考資料
ofollow,noindex">左神牛課網演算法課