
🎬 博主名称 :键盘敲碎了雾霭
🔥 个人专栏 : 《C语言》《数据结构》 《C++》 《Matlab》 《Python》
⛺️指尖敲代码,雾霭皆可破

文章目录
- 一、常用接口介绍
-
- [1.1 stack](#1.1 stack)
- [1.2 queue](#1.2 queue)
- 二、常见面试题
-
- [2.1 最小栈](#2.1 最小栈)
- [2.2 栈的压入、弹出序列](#2.2 栈的压入、弹出序列)
- [2.3 用栈实现队列](#2.3 用栈实现队列)
- [2.4 用队列实现栈](#2.4 用队列实现栈)
- [2.5 二叉树的层序遍历](#2.5 二叉树的层序遍历)
- 三、模拟实现
-
- [3.1 stack](#3.1 stack)
- [3.2 queue](#3.2 queue)
- 四、deque
-
- [4.1 deque的引入](#4.1 deque的引入)
- [4.2 底层结构](#4.2 底层结构)
- [4.3 总结](#4.3 总结)
- 五、优先级队列
- [5.1 应用](#5.1 应用)
- [5.2 模拟实现](#5.2 模拟实现)
- 文章结语
一、常用接口介绍
1.1 stack
因为使用比较简单
详见文档 :https://legacy.cplusplus.com/reference/stack/stack/?kw=stack


1.2 queue
详见文档 :https://legacy.cplusplus.com/reference/queue/queue/?kw=queue


二、常见面试题
2.1 最小栈
代码实现
cpp
class MinStack
{
public:
MinStack()
{
}
void push(int val)
{
st1.push(val);
if(st2.empty()||st1.top()<=st2.top())
{
st2.push(val);
}
}
void pop()
{
if(st1.top()==st2.top())
{
st2.pop();
}
st1.pop();
}
int top()
{
return st1.top();
}
int getMin()
{
return st2.top();
}
private:
stack<int> st1;
stack<int> st2;
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
2.2 栈的压入、弹出序列
cpp
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pushV int整型vector
* @param popV int整型vector
* @return bool布尔型
*/
bool IsPopOrder(vector<int>& pushV, vector<int>& popV) {
// write code here
stack<int> st;
int i = 0;
for (auto e : pushV) {
st.push(e);
while (!st.empty() && popV[i] == st.top()) {
st.pop();
++i;
}
}
return st.empty();
}
};
2.3 用栈实现队列
题目描述:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作push、pop、peek、empty)
cpp
class MyQueue {
public:
MyQueue()
{
}
void push(int x)
{
st1.push(x);
}
int pop()
{
int tmp = peek();
st2.pop();
return tmp;
}
int peek()
{
if(st2.empty())
{
while(!st1.empty())
{
st2.push(st1.top());
st1.pop();
}
}
return st2.top();
}
bool empty()
{
return st1.empty()&&st2.empty();
}
private:
stack<int> st1;
stack<int> st2;
};
/**
* 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();
*/
2.4 用队列实现栈
cpp
class MyStack {
public:
MyStack()
{
}
void push(int x)
{
if(!q1.empty())
{
q1.push(x);
}
else
{
q2.push(x);
}
}
int pop()
{
if(q1.empty())
{
while(q2.size()>1)
{
q1.push(q2.front());
q2.pop();
}
int tmp =q2.front();
q2.pop();
return tmp;
}
else
{
while(q1.size()>1)
{
q2.push(q1.front());
q1.pop();
}
int tmp=q1.front();
q1.pop();
return tmp;
}
}
int top()
{
if(q1.empty())
{
return q2.back();
}
else
{
return q1.back();
}
}
bool empty()
{
return q1.empty()&&q2.empty();
}
private:
queue<int> q1;
queue<int> q2;
};
/**
* 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();
*/
2.5 二叉树的层序遍历
cpp
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<vector<int>> levelOrder(TreeNode* root)
{
vector<vector<int>> vv;
queue<TreeNode*> q;
int size=0;
if(root)
{
q.push(root);
size++;
}
while(!q.empty())
{
vector<int> v;
while(size--)
{
TreeNode* front=q.front();
v.push_back(front->val);
q.pop();
if(front->left)
{
q.push(front->left);
}
if(front->right)
{
q.push(front->right);
}
}
size=q.size();
vv.push_back(v);
}
return vv;
}
};
三、模拟实现
由于stack和queue都是适配器,可以直接传容器类型进去,适配器是一种设计模式,该种模式是将一个类的接口转换成客户希望的另外一个接口。
3.1 stack
cpp
#pragma once
#include<iostream>
#include<deque>
#include<vector>
#include<list>
namespace A
{
template<class T,class Contain=deque<T>>
class stack
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
const T& top()const
{
return _con.back();
}
size_t size()const
{
return _con.size();
}
bool empty()const
{
return _con.empty();
}
private:
Contain _con;
};
}
3.2 queue
cpp
#pragma once
namespace A
{
template<class T,class Contain=deque<T>>
class Queue
{
public:
void push(const T&x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_front();
}
const T& front()
{
return _con.front();
}
const T& back()
{
return _con.back();
}
size_t size()const
{
return _con.size();
}
bool empty()const
{
return _con.empty();
}
private:
Contain _con;
};
}
四、deque
4.1 deque的引入
deque相当于vector与list的缝合怪,两者的特点都有
deque(双端队列):是一种双开口的"连续"空间的数据结构 ,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高

4.2 底层结构
deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组

4.3 总结
- deque头插尾插效率很高,更甚于vector和list
- 下标随机访问也还不错,相比vector略逊一筹
- 中间插入删除效率很低,要挪动数据,是O(N)
五、优先级队列
具体文档:https://legacy.cplusplus.com/reference/queue/priority_queue/?kw=priority_queue


5.1 应用
cpp
#include<queue>
#include<iostream>
using namespace std;
int main()
{
priority_queue<int> qu;
qu.push(1);
qu.push(9);
qu.push(5);
qu.push(4);
while (!qu.empty())
{
cout << qu.top() << " ";
qu.pop();
}
cout << endl;
return 0;
}
5.2 模拟实现
通过仿函数,可以模拟实现
cpp
#pragma once
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
template<class T>
class Great
{
public:
bool operator()(const T& x, const T& y)
{
return x > y;
}
};
template<class T>
class Less
{
public:
bool operator()(const T& x, const T& y)
{
return x < y;
}
};
namespace A
{
template<class T,class Contain=vector<T>,class Compare=Less<T>>
class priority_queue
{
Compare com;
void AdjustUp(int child)
{
int parent = (child - 1) / 2;
while (child > 0)
{
if (com(_con[parent] , _con[child]))
{
swap(_con[parent], _con[child]);
}
else
{
break;
}
child = parent;
parent = (child - 1) / 2;
}
}
void AdjustDown(int parent)
{
int child = parent * 2 + 1;
while (child < _con.size())
{
if (child + 1< _con.size() && com(_con[child] , _con[child + 1]))
{
child++;
}
if ( com( _con[parent], _con[child]))
{
swap(_con[child], _con[parent]);
}
else
{
break;
}
parent = child;
child = parent * 2 + 1;
}
}
public:
void push(const T& x)
{
_con.push_back(x);
AdjustUp(_con.size() - 1);
}
void pop()
{
swap(_con[0], _con[_con.size() - 1]);
_con.pop_back();
AdjustDown(0);
}
bool empty()const
{
return _con.empty();
}
const T& top()const
{
return _con[0];
}
size_t size()const
{
return _con.size();
}
private:
Contain _con;
};
}
文章结语
感谢你读到这里~我是「键盘敲碎了雾霭」,愿这篇文字帮你敲开了技术里的小迷雾 💻
如果内容对你有一点点帮助,不妨给个暖心三连吧👇
👍 点赞 | ❤️ 收藏 | ⭐ 关注
(听说三连的小伙伴,代码一次编译过,bug绕着走~)
你的支持,就是我继续敲碎技术雾霭的最大动力 🚀
🐶 小彩蛋:
/^ ^\
/ 0 0 \
V\ Y /V
/ - \
/ |
V__) ||
摸一摸毛茸茸的小狗,赶走所有疲惫和bug~我们下篇见 ✨