栈与队列
基础知识
栈:后进先出 LIFO
队列:先进先出 FIFO
这里介绍的栈和队列是SGI STL中的数据结构
三个最为普遍的STL(C++标准模板库)版本:
- HP STL 是C++ STL的第一个实现版本,且开放源代码,其他版本的C++ STL,一般是以HP STL为蓝本实现
- P.J.Plauger STL 由P.J.Plauger参照HP STL实现,被Visual C++编译器所采用,不开源
- SGI STL 由Silicon Graphics Computer Systems公司参照HP STL实现,被Linux的C++编译器GCC所采用,SGI STL是开源软件,源码可读性甚高
栈stack
和队列queue
的所有元素必须符合先进后出/先进先出规则,所以不提供走访功能,也不提供迭代器(iterator)来遍历所有元素
stack
和queue
不是容器(Container),而是容器适配器(Container Adapter)
stack
和queue
默认基于 deque
(双端队列)实现,但允许用户指定其他底层容器(如 list
或 vector
,一般queue
不能使用vector
,因为 vector
不支持 pop_front()
)
标准容器(如
vector
、list
、deque
)直接管理自己的内存和元素容器适配器仅对底层容器进行接口限制,以实现特定行为,基于现有的容器封装而成,提供特定接口(如后进先出 LIFO 操作),但底层存储和实现依赖于其他容器
基础语句
// 栈
std::stack<int, std::vector<int>> third; // 定义以vector为底层容器的栈
stack.push(val); // 将元素压入栈顶 O(1),依赖底层容器的 push_back()
stack.pop(); // 移除栈顶元素(无返回值) O(1),依赖底层容器的 pop_back()
stack.top(); // 返回栈顶元素(不移除) O(1),依赖底层容器的 back()
stack.empty(); // 检查栈是否为空 O(1),返回bool,直接调用底层容器的 empty()
stack.size(); // 返回栈中元素数量 O(1),调用底层容器的 size()
// 队列
std::queue<int, std::list<int>> third; // 定义以list为底层容器的队列
queue.push(val); // 将元素插入队尾 O(1),依赖底层容器的 push_back()
queue.pop(); // 移除队首元素(无返回值) O(1),依赖底层容器的 pop_front()
queue.front(); // 返回队首元素(不移除) O(1),依赖底层容器的 front()
queue.back(); // 返回队尾元素(不移除) O(1),依赖底层容器的 back()
queue.empty(); // 检查队列是否为空 O(1) ,返回bool,直接调用底层容器的 empty()
queue.size(); // 返回队列中元素数量 O(1),调用底层容器的 size()
模拟栈与队列
232# 用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(
push
、pop
、peek
、empty
):实现
MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回true
;否则,返回false
说明:
- 你 只能 使用标准的栈操作 —— 也就是只有
push to top
,peek/pop from top
,size
, 和is empty
操作是合法的。- 你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
示例 1:
输入: ["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 1, 1, false] 解释: MyQueue myQueue = new MyQueue(); myQueue.push(1); // queue is: [1] myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue) myQueue.peek(); // return 1 myQueue.pop(); // return 1, queue is [2] myQueue.empty(); // return false
提示:
1 <= x <= 9
- 最多调用
100
次push
、pop
、peek
和empty
- 假设所有操作都是有效的 (例如,一个空的队列不会调用
pop
或者peek
操作)
需要两个栈一个输入栈,一个输出栈,先进后出+后进先出实现先进先出
在push
时,只需将数据放进输入栈,但在pop
时,需要从输出栈弹出数据,如果输出栈为空,就把输入栈的数据全部导入输出栈
// 栈模拟队列
// O(1) 0ms; O(n) 9.62MB
class MyQueue {
private:
stack<int> stIn, stOut;
public:
MyQueue() {
}
void push(int x) {
// O(1)
stIn.push(x);
}
int pop() {
// 均摊O(1)
int front = this->peek();
stOut.pop();
return front;
}
int peek() {
// 均摊O(1)
if (stOut.empty()) {
while (!stIn.empty()) {
stOut.push(stIn.top());
stIn.pop();
}
}
return stOut.top();
}
bool empty() {
// O(1)
return stIn.empty() && stOut.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();
*/
225# 用队列实现栈
请你仅使用队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(
push
、top
、pop
和empty
)。实现
MyStack
类: