棧與佇列
阿新 • • 發佈:2021-01-10
佇列:先進先出
棧:先進後出
幾個基礎的問題:
- C++中stack 是容器麼?
- 我們使用的stack是屬於那個版本的STL?
- 我們使用的STL中stack是如何實現的?
- stack 提供迭代器來遍歷stack空間麼?
棧和佇列和C++STL裡面的兩個資料結構。
棧:先進後出
棧提供push、pop等介面,所有元素必須符合先進後出規則,所以棧不提供走訪功能,也不提供迭代器iterator,不像是set或者是map提供迭代器來遍歷所有元素。
「棧是以底層容器完成其所有的工作,對外提供統一的介面,底層容器是可插拔的(也就是說我們可以控制使用哪種容器來實現棧的功能)。」
所以STL中棧往往不被歸類為容器,而被歸類為container adapter(容器介面卡)
「我們常用的SGI STL,如果沒有指定底層實現的話,預設是以deque為預設情況下棧的低層結構。」
deque是一個雙向佇列,只要封住一段,只開通另一端就可以實現棧的邏輯了。
「SGI STL中 佇列底層實現預設情況下一樣使用deque實現的。」
我們也可以指定vector為棧的底層實現
佇列 先進先出的資料結構,同樣不允許有遍歷行為,不提供迭代器,SGI STL中佇列一樣是以deque為預設情況下的底部結構。
也可以指定list 為起底層實現
所以STL中佇列也不被歸類為容器,而被歸類為container adapter( 容器介面卡)。
可以用棧來實現佇列:兩個棧可以實現佇列!
classMyQueue { public: stack<int> stIn; stack<int> stOut; /** Initialize your data structure here. */ MyQueue() { } /** Push element x to the back of queue. */ void push(int x) { stIn.push(x); } /** Removes the element from in front of queue and returns that element.*/ int pop() { if(stOut.empty()) { while(!stIn.empty()) { stOut.push(stIn.top()); stIn.pop(); } } int result = stOut.top(); stOut.pop(); return result; } /** Get the front element. */ int peek() { int res = this->pop();//這裡彈出了res stOut.push(res); return res; } /** Returns whether the queue is empty. */ bool empty() { return (stOut.empty() && stIn.empty()); } }; /** * Your MyQueue object will be instantiated and called as such: * MyQueue* obj = new MyQueue(); * obj->push(x); * int param_2 = obj->pop(); * int param_3 = obj->peek(); * bool param_4 = obj->empty(); */
可以用佇列還實現棧!
class MyStack { public: queue<int>que1; queue<int>que2;//用來備份的 /** Initialize your data structure here. */ MyStack() { } /** Push element x onto stack. */ void push(int x) { que1.push(x); } /** Removes the element on top of the stack and returns that element. */ int pop() { //現在元素都在que1裡,隊尾的元素是需要pop的元素,需要把其他的都暫存到que2裡 int size = que1.size(); size--; while(size--) { que2.push(que1.front()); que1.pop(); } int result = que1.front(); que1.pop(); que1 = que2;//恢復que1 while(!que2.empty()) que2.pop(); return result; } /** Get the top element. */ int top() { return que1.back(); } /** Returns whether the stack is empty. */ bool empty() { return que1.empty(); } }; /** * Your MyStack object will be instantiated and called as such: * MyStack* obj = new MyStack(); * obj->push(x); * int param_2 = obj->pop(); * int param_3 = obj->top(); * bool param_4 = obj->empty(); */
一個經典應用就是“有效的括號”問題。
逆波蘭表示式問題是棧的經典應用,也是一道比較難的題目,題目一定要記住一個規則:遇到數字則入棧;遇到算符則取出兩個數字進行計算,並將結果壓入棧中。
class Solution { public: int evalRPN(vector<string>& tokens) { stack<int> st; for(int i=0; i<tokens.size(); i++) { if(tokens[i]=="+" || tokens[i]=="-" || tokens[i]=="*" || tokens[i]=="/") {//這裡一定要注意是雙引號 int num1 = st.top(); st.pop(); int num2 = st.top(); st.pop(); if(tokens[i]=="+") st.push(num1+num2); else if(tokens[i]=="-") st.push(num2-num1);//這裡一定要注意相減的順序 else if(tokens[i]=="*") st.push(num1*num2); else//除法 st.push(num2/num1);//這裡一定要注意相除的順序 } else st.push(stoi(tokens[i])); } int result = st.top(); st.pop(); return result; } };