目录
栈应用举例
std::stack的基本操作:
队列实现栈
c++版单队列方式
python3
应用实例(一):括号匹配
C++栈
C++非栈方式
python实现
实例(二):后缀表达式求值
c++实现
python实现
队列的应用
队:
std::queue 基本操作
栈实现队列
队列应用举例:
1、约瑟夫问题
数组实现:
队列实现:
双向链表
2、单调队列-滑动窗口里的最大值
C++
python3
总结
栈是操作受限的线性表,典型生活中的用例:压入子弹。std::stack
类是一种容器适配器,底层实现默认是deque,它给予栈的功能,FILO(先进后出)。该类模板用做为底层容器的包装器,只提供特定函数集合。栈从被称作栈顶的容器尾部弹元素。
C++ stack的基本操作 | ||
s.pop() | 修改器 | 删除栈顶元素,但不返回该元素的值 |
swap() | 交换元素 | |
s.push(item) | 创建一个新元素压入栈顶,该元素通过拷贝或移动item而来,或者由args构造 | |
s.emplace(args) | ||
s.top() | 元素访问 | 返回栈顶元素,但是不将元素弹出栈 |
empty()、size() | 容量 | empty检查容器是否为空,size返回元素数 |
栈默认基于deque实现,也可以在list或vector之上实现 |
#include
#include
using namespace std;
int main() {
stack s;
// push() 压入元素
s.push(1);
s.push(2);
s.push(3);
//容量
cout << "s.size() = " << s.size() << endl;
cout << "s.empty() = " << s.empty() << endl;
if (!s.empty())
cout << "栈顶元素s.top() = " << s.top() << endl;
//元素访问
s.pop(); // 弹出栈顶元素
cout << "s.size() = " << s.size() << " s.empty() = " << s.empty() << endl;
if (!s.empty())
cout << "s.top() = " << s.top() << endl;
//推入新元素到 stack 顶。原位构造元素,即不进行移动或复制操作
s.emplace(3);
stack s1;//空栈
s1.swap(s); // s和s1进行交换
cout << "s.size() = " << s.size() << " s.empty() = " << s.empty() << endl;
if (!s.empty())
cout << "栈顶元素,即s.top() = " << s.top() << endl;
else
cout << "栈空不能使用top访问栈顶元素" << endl;
cout << "s1.size() = " << s1.size() << " s1.empty() = " << s1.empty() << endl;
if (!s1.empty())
cout << "栈顶元素,即s1.top() = " << s1.top() << endl;
return 0;
}
class MyStack {
queue qunIn; //单队列方式
public:
MyStack() {
}
void push(int x) { //模拟入栈
int n=qunIn.size();
qunIn.push(x);
for(int i=0;i
class MyStack:
def __init__(self):
self.queue=deque()
def push(self, x: int) -> None:
n=len(self.queue)
self.queue.append(x)
for _ in range(n):
self.queue.append(self.queue.popleft())
def pop(self) -> int:
return self.queue.popleft()
def top(self) -> int:
return self.queue[0]
def empty(self) -> bool:
return not self.queue
输入给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效
bool isValid(string s) {
stack sta;
if (s.size() % 2 == 1) {
return false;
}
for (auto ch : s) {
if (sta.empty() || ch == '{' || ch == '[' || ch == '(') {
sta.push(ch);
} else if (ch == ']' && !sta.empty() && sta.top() == '[')
sta.pop();
else if (ch == '}' && !sta.empty() && sta.top() == '{')
sta.pop();
else if (ch == ')' && !sta.empty() && sta.top() == '(')
sta.pop();
else
sta.push(ch);
}
return sta.empty();
}
bool isValid(string s) {
int len=s.length()/2;
std::string::size_type n;
for(int i=0;i
class Solution:
def isValid(self, s: str) -> bool:
if len(s)%2:
return False
mp={')':'(',']':'[','}':'{'}
st=[]
for c in s:
if c not in mp: #c is 左括号
st.append(c) #
elif not st or st.pop()!=mp[c]:
return False
return not st #匹配结束左括号要匹配完
int evalRPN(vector &tokens)
{
std::stack st;
for (auto i : tokens)
{
if (i.size() > 1 || isdigit(i[0]))
{
st.emplace(stoi(i));
}
else
{
try
{
if (st.empty())
{
throw std::out_of_range("Stack is empty, cannot pop");
}
int n2 = st.top();
st.pop();
if (st.empty())
{
throw std::out_of_range("Stack is empty, cannot pop");
}
int n1 = st.top();
st.pop();
if (i == "+")
n1 = n1 + n2;
else if (i == "-")
n1 = n1 - n2;
else if (i == "*")
n1 = n1 * n2;
else if (i == "/")
n1 = n1 / n2;
st.emplace(n1);
}
catch (const std::exception &e)
{
std::cerr << e.what() << '\n';
}
}
}
return st.top();
}
#计算后缀表达式的值
# 后缀表达式(也称为逆波兰表达式)是一种算术表达式,其中操作符位于其操作数之后。
from typing import List
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
stack=[]
calc={'+':lambda x,y:x+y,
'-':lambda x,y:x-y,
'*':lambda x,y:x*y,
'/':lambda x,y:int(x/y)}
for i in tokens:
if i in calc:
try:
n2,n1=stack.pop(),stack.pop()
stack.append(calc[i](n1,n2))
except ZeroDivisionError:
print('division by zero')
return None
except IndexError:
print('not right evalRPN ')
return None
else:
stack.append(int(i))
return stack[0]
so =Solution()
print(so.evalRPN(['0','/','/']))
一种先进先出的数据结构,std::queue也是一种容器适配器,遵循先进先出FIFO原则,其中从容器一端插入元素,另一端提取元素。
priority_queue是C++标准库中的一个容器适配器,用于实现优先队列的数据结构。优先队列是一种特殊的队列,其中的元素按照一定的优先级进行排序,每次取出的元素都是优先级最高的。它的底层实现通常使用堆(heap)数据结构。它提供常数时间的(默认)最大元素查找,对数代价的插入与提取。可以通过用户提供的 Compare
更改顺序,例如,用 std::greaterpriority_queue
的作用类似于管理某些随机访问容器中的堆,其优势是不可能意外使堆失效。
C++的队列适配器queue和priority_queue适配器定义在queue头文件中,queue默认基于deque实现,也可以用list或vector实现,priority_queue默认基于vector实现,也可以用deque实现 | |
q.pop() | 移除quene的首元素或priority_queue的最高优先级的元素 |
q.front() | 返回首元素或尾元素,但是不删除此元素,q.back只适用于quene |
q.back() | |
q.top() | 返回最高优先级元素不删除该元素只适用于priority_queue |
q.push(item) | 在queue末尾或priority_queue中恰当位置创建一个值为item的元素或者由args构造 |
q.emplace(args) |
#include
#include
using namespace std;
int main()
{
queue q; //默认使用 deque
//queue> qVector; //指定使用 vector
q.push(1);
q.push(2);
q.push(3);
cout << q.size() << endl; //元素个数 size() 3
cout << q.front() << endl; //队头元素 front() 1
cout << q.back() << endl; //队尾元素 队尾元素back() 3
q.pop(); // 出队pop()
cout << q.size() << endl; //2
cout << q.front() << endl; //2
while (!q.empty()) //判空 empty()
{
cout << q.front() << " "; //2 3
q.pop();
}
cout << q.size() << endl; //0
queue q1;
q1.push(4);
q1.push(5);
q1.push(6);
cout <<"before swap q size is "<< q.size() <<" before swap q1 size is "< pq; //直接构造一个空对象,默认为大堆
priority_queue, std::greater> pq1; // 构建小堆
cout<<"----------priority_queue----"< pq2; //直接构造一个空对象,默认为大堆
cout<
class MyQueue {
private:
stack staIn;
stack staout;
public:
MyQueue() {
}
void push(int x) { //入栈模拟入队
staIn.push(x);
}
int pop() {
if(staout.empty()){ //出队是入栈不能有元素,保证出栈是先入队元素
while (!staIn.empty())
{
staout.push(staIn.top());
staIn.pop();
}
}
int res=staout.top();
staout.pop();
return res;
}
int peek() {
int res=this->pop();
staout.push(res);
return res;
}
bool empty() {
return staIn.empty()&&staout.empty();
}
};
N个人围成一圈从第一个人开始报数,数到M的人出圈;再由下一个人开始报数,数到M的人出圈
#include
#include
using namespace std;
int main(){
int n,m,flag=0;
cin>>n>>m;
int count=0,len=1,arr[n+1]={0};
for(int i=1;i<=n;i++){
arr[i]=i;
}
while(flag!=n)//一共n个人
{
if(arr[len]!=0){//如果数组不为0,就计数已经输出的人将其值赋值为了0
count++;
}
if(count==m)//计数值为m输出该点的值并将其赋值为0
{
count=0;
cout<
#include
using namespace std;
int main()
{
queue que;
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; ++i)
que.push(i);
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= m - 1; ++j)
{//将队头的人出队后,再入队到队尾
que.push(que.front());
que.pop();
}
cout << que.front() << ' ';//此时队头是要出列的人
que.pop();
}
return 0;
}
#include
using namespace std;
int main()
{
list li;
int n, m, ct = 0;
cin >> n >> m;
for(int i = 1; i <= n; ++i)
li.push_back(i);
list::iterator it = li.begin();
while(li.empty() == false)
{
ct++;
if(ct == m)
{
cout << *it << ' ';
it = li.erase(it);
ct = 0;
}
else
it++;
if(it == li.end())
it = li.begin();
}
return 0;
}
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7]
vector maxSlidingWindow(vector& nums, int k) {
deque res;
vector result;
for(int i=0;i=k){ //队首出队
res.pop_front();
}
if(i>=k-1){ //单调性最值在队首
result.push_back(nums[res.front()]);
}
}
return result;
}
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
ans=[]
q=deque()
for i, x in enumerate(nums):
while q and nums[q[-1]]<=x:
q.pop() #维护单调性
q.append(i) #入队
if i-q[0]>=k: #元素即将多于k,队首离队
q.popleft()
if i>=k-1: #取最大值队首
ans.append(nums[q[0]])
return ans
栈常用于 1)函数调用管理:程序的函数调用使用栈来管理局部变量和返回地址。2)表达式求值:在计算机中,栈用于表达式的求值和语法解析(如中缀表达式转后缀表达式)。3)回溯算法:如深度优先搜索(DFS)等算法中,栈用于存储路径信息。4)撤销操作:在文本编辑器等应用中,栈可以用于实现撤销功能。
队列常用于:1)任务调度:操作系统中的任务调度使用队列来管理进程或线程的执行顺序。2)数据流管理:在网络数据包处理、IO缓冲等场景中,队列用于管理数据流。3)广度优先搜索(BFS)在图的遍历中,队列用于存储待访问的节点。4)打印任务管理:打印机的任务管理使用队列来处理打印请求。