目錄
- 基本性質
- 棧和隊列的基本操作
- 雙端隊列和優先級隊列
- 深度優先遍歷(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