栈与队列理论基础 - 筆記
Stack
先進後出,想像成羽球桶,先放進去的一定最後才可以拿的到,除非只有一顆
Queue
先進先出,想像成珍珠奶茶的大吸管,先進到吸管的珍珠一定是先進去嘴巴裡
問題紀錄
-
C++中stack 、queue是容器么?
不是容器,底層的實現是可以換得,stack主要是提供統一的處理邏輯。
是被歸類為container adapter,有點像是吸管,我們可以插在不同的飲料杯上面,接口一樣,底層飲料不一樣
-
我们使用的stack、queue是属于哪个版本的STL?
目前主要使用SGI STL
Silicon Graphics Computer Systems公司参照HP STL實現,被Linux的C++ 編譯器 GCC採用
-
我们使用的STL中stack、queue是如何实现的?
SGI 底層默認是使用deqeue實現的,但我們也可以改成vector、list去實現
-
stack 初始化使用 vector
std::stack<int, std::vector<int>> stack_vector;
-
list 初始化使用 list
std::stack<int, std::list<int>> queue_list;
-
-
stack 、queue提供迭代器来遍历stack空间么?
不提供,就像喝珍珠奶茶你只知道你接下來會吸到珍珠跟奶茶,但是除非把珍珠奶茶全部倒出來,不然你沒辦法看到原料的全貌。
讀題
232.用栈实现队列
自己看到题目的第一想法
看到題目感覺蠻有趣的,這兩個不同資料處理的方式,用Stack的操作來實現Queue的操作,如果要將先進後出變成先進先出,那就會需要兩個數組來實現,第一個數組就是正常的stack push的操作→ 模擬queue enqueue,但如果要deqeue則要先將第一個數組的值都放到第二個數組,再由第二個數組來做pop的動作,類似以下做法,如果要找rear用第一個數組的top,找front就用第二個數組的top
看完代码随想录之后的想法
整體思路跟我想得很像,但我把事情想太複雜了,push的部分我就直接push,要pop的時候我再來判斷我原本的pop裡面有沒有元素,沒有的話我把之前的push全部放在第二個數組,另外我對於C++的函數操作太不熟悉了,導致雖然有想法,但不知道怎麼實現,出現了很多函數誤用的狀況,對於函數的初始化也不熟悉,只能邊看邊學了
232.用队列实现栈
自己看到题目的第一想法
用Queue來實現Stack就有點像是把吸管的一邊給封住,如要enqeue造著原本的方式加入rear - > front ,dequeu也是從rear to front,因為原本deqeueu 是從front to rear,翻轉這部分就會實現Stack了
看完代码随想录之后的想法
再實現時因為有看卡哥的提示嘗試著使用一個對列去做解決,後面再做pop的時候出現問題,就去看講解,才發現自己的移動元素的思路沒錯,但數量錯了,導致順序錯亂。
232.用栈实现队列 - 實作
思路
錯誤思路
- 建立兩個stack,一個處理push一個處理pop
- push - queue_vector_push.push();
- 將全部queue_vector_push.pop放入queue_vector_push.push
- queue_vector_push(queue_vector_pop.pop());
- return queue_vector_pop.pop();
- pop
- 將全部queue_vector_push.push放入queue_vector_push.pop
- queue_vector_pop(queue_vector_push.pop());
- return queue_vector_pop.pop();
- peek
- 將全部queue_vector_push.push放入queue_vector_push.pop
- queue_vector_pop(queue_vector_push.pop());
- return queue_vector_pop.peak();
- empty
- 兩個都empty才return true;
正確思路
- 建立兩個stack,一個處理push一個處理pop
- push - queue_vector_push.push(x);
- pop
- 假設queue_vector_pop.empty() == true
- 將queue_vector_push所有資料丟入queue_vector_pop
- queue_vector_pop
- 取最上面的值
- 將最上面的值丟棄
- 假設queue_vector_pop.empty() == true
- peek
- 取用pop函數,拿到最上面的值存入變數
- 再將push變數回stack
- return 變數
- empty
- 兩個都empty才return true;
Code
錯誤代碼
class MyQueue {
public:
MyQueue() {
}
void push(int x) {
while(queue_vector_pop.peek() != NULL) {
queue_vector_push.push(queue_vector_pop.pop());
}
queue_vector_push.push(x);
}
int pop() {
while(queue_vector_push.peek() != NULL){
queue_vector_pop.push(queue_vector_push.pop());
}
return queue_vector_pop.pop();
}
int peek() {
while(queue_vector_push.peek() != NULL){
queue_vector_pop.push(queue_vector_push.pop());
}
return queue_vector_pop.peek();
}
bool empty() {
if(queue_vector_pop.peek() == NULL && queue_vector_push.peek() == NULL) return true;
return false
}
private:
std::stack<int, std::vector<int>> queue_vector_push;
std::stack<int, std::vector<int>> queue_vector_pop;
};
正確代碼
class MyQueue {
public:
stack<int> queue_vector_push;
stack<int> queue_vector_pop;
MyQueue() {
}
void push(int x) {
queue_vector_push.push(x);
}
int pop() {
if(queue_vector_pop.empty()) {
while(!queue_vector_push.empty()) {
queue_vector_pop.push(queue_vector_push.top());
queue_vector_push.pop();
}
}
int result = queue_vector_pop.top();
queue_vector_pop.pop();
return result;
}
int peek() {
int res = this->pop();
queue_vector_pop.push(res);
return res;
}
bool empty() {
return queue_vector_pop.empty() && queue_vector_push.empty();
}
};
225. 用队列实现栈 - 實作
思路
錯誤思路
- push就直接push
- pop
- 將對列最前面的元素放到對列的最後,最後輸出最前面的元素
- top
- 將對列最後的元素顯示
- empty → 等同queu empty
正確思路
-
push就直接push
-
pop
- 將對列最前面的元素放到對列的最後,最後輸出最前面的元素
<aside> 💡 因為我要是將最後面的元素pop出來,我實際上要移到後面的元素數量是size-1,所以,我沒有減一就會導致順序出現問題
</aside>
-
top
- 將對列最後的元素顯示
-
empty → 等同queu empty
Code
class MyStack {
public:
queue<int> q;
MyStack() {
}
void push(int x) {
q.push(x);
}
int pop() {
for(int i = 0; i < q.size(); i++) {
q.push(q.front());
q.pop();
}
int res = q.front();
q.pop();
return res;
}
int top() {
int res = q.back();
return res;
}
bool empty() {
return q.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 MyStack {
public:
queue<int> q;
MyStack() {
}
void push(int x) {
q.push(x);
}
int pop() {
for(int i = 0; i < q.size() - 1; i++) {
q.push(q.front());
q.pop();
}
int res = q.front();
q.pop();
return res;
}
int top() {
int res = q.back();
return res;
}
bool empty() {
return q.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();
*/
總結
自己实现过程中遇到哪些困难
今天整體還是比較簡單的,主要的困難點是在C++庫函數不熟悉,以及對於一些小細節沒有注意到
今日收获,记录一下自己的学习时长
今天大概學了2hr,整體主要就是熟悉Stack 以及 Queue的操作
相關資料
理论基础
文章讲解:https://programmercarl.com/栈与队列理论基础.html
232.用栈实现队列
题目链接/文章讲解/视频讲解:https://programmercarl.com/0232.用栈实现队列.html
225. 用队列实现栈
题目链接/文章讲解/视频讲解:https://programmercarl.com/0225.用队列实现栈.html