STL容器适配器之<queue>
Posted SiveenWS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL容器适配器之<queue>相关的知识,希望对你有一定的参考价值。
文章目录
测试环境
系统:ubuntu 22.04.2 LTS 64位
gcc版本:11.3.0
编辑器:vsCode 1.76.2
queue介绍
- queue为容器适配器。
- 支持在末端插入元素,在首端删除元素。
- 不支持随机访问。
- 先进先出规则(FIFO)
- 默认基础容器为deque,还可以使用list作为基础容器,或者支持front()、pop_front()、back()、push_buck()的其他容器。
头文件
#include <queue>
模块类定义
_Tp:表示存储的元素数据类型
_Alloc:表示所存储分配器的类型,负责元素内存的分配和释放。可选参数,一般不使用。
template<typename _Tp, typename _Sequence = deque<_Tp> > class queue;
对象构造
/*构造默认栈对象*/
std::queue<int> queueInt;
/*构造以deque作为基础容器的栈*/
std::queue<int, std::deque<int> > deqQueue;
/*构造以deque作为基础容器的栈*/
std::queue<int, std::vector<int> > vctQueue;
/*构造以list作为基础容器的栈*/
std::queue<int, std::list<int> > lstQueue;
/*从链表中构造对象并将链表中的数据作为队列数据*/
std::list<int> lst(1,2,3);
std::queue<int, std::list<int> > lstQueue1(lst);
初始化
/*初始化*/
deqQueue.push(100);
deqQueue.push(200);
deqQueue.push(300);
元素访问
函数名 | 返回值 | 功能 |
---|---|---|
front() | 首元素的引用 | 获取首元素,队列为空时返回值不确定 |
back() | 尾元素的引用 | 获取末尾元素,队列为空时返回值不确定 |
/*获取队头元素*/
int &iFrontVal = deqQueue.front();
std::cout << iFrontVal << std::endl;
/*修改队头元素*/
iFrontVal = 66;
std::cout << deqQueue.front() << std::endl;
/*获取队尾元素*/
int &iBackVal = deqQueue.back();
std::cout << iBackVal << std::endl;
/*修改队尾元素*/
iBackVal = 88;
std::cout << deqQueue.back() << std::endl;
元素插入和删除
函数 | 返回值 | 功能 |
---|---|---|
pop() | 无 | 删除队列头元素 |
push() | 无 | 队列尾插入元素 |
/*在链表头插入元素*/
deqQueue.push(88);
/*删除链表头部元素*/
deqQueue.pop();
容器大小
函数 | 返回值 | 功能 |
---|---|---|
empty() | bool | 判断当前容器是否为空,为空返回true,否则返回false |
size() | std::size_t | 获取当前容器中的元素数量 |
/*判断队列是否为空*/
std::cout << std::boolalpha << queueInt.empty() << std::endl;
/*获取队列中元素数量*/
std::cout << deqQueue.size() << std::endl;
迭代器
不支持
其他函数
函数名 | 返回值 | 功能 |
---|---|---|
swap() | 无 | 交换两个容器的元素 |
/*交互两个容器元素的值,无返回值*/
std::queue<int> queSwap1 = 1,2,3,4,5;
std::queue<int> queSwap2 = 5,4,3,2,1;
/*方式1, queSwap1=5,4,3,2,1, queSwap2=1,2,3,4,5*/
queSwap1.swap(queSwap2);
/*方式2,queSwap1=1,2,3,4,5, queSwap2=5,4,3,2,1*/
std::swap(queSwap1,queSwap2);
STL容器适配器stack和queue
STL容器适配器——stack、queue
什么是适配器? 适配器是一种设计模式(设计模式是一套被反复使用的。多数人知晓的、经过分类编目的、代码设计经验的总结),该模式是将一个类的接口转换成各户希望的另外一个接口。前言
stack和queue是作为STL的容器适配器被实现的,容器适配器暨是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层。
一、stack
1.基本使用
先来看一下MSDN里面对stack的简单介绍
我们再来看一下stack简单的使用。
void main()
{
stack<int> st;//容器适配器
for (int i = 1; i <= 10; ++i)//将1到10顺序入栈
{
st.push(i);
}
cout << "st.size = " << st.size() << endl;
while (!st.empty())//顺序出栈
{
int value = st.top();
st.pop();
cout << value << endl;
}
//无法通过迭代器访问
}
给个题理解一下。
155.最小栈
题解:
class MinStack {
public:
/** initialize your data structure here. */
MinStack()
{}
void push(int val)
{
data_st.push(val);
if(min_st.empty() || val<=min_st.top())
min_st.push(val);
}
void pop()
{
int val = data_st.top();
data_st.pop();
if(val == min_st.top())
min_st.pop();
}
int top()
{
return data_st.top();
}
int getMin()
{
return min_st.top();
}
private:
stack<int> data_st;
stack<int> min_st;
};
2.模拟实现
从栈的接口中可以看出,栈实际是一种特殊的vector,因此使用vector完全可以模拟实现stack。
namespace LJL
{
template<class _Ty>
class stack
{
public:
stack()
{}
~stack()
{}
public:
bool empty()const
{
return _C.empty();
}
size_t size()const
{
return _C.size();
}
_Ty& top()
{
return _C.back();
}
const _Ty& top()const
{
return _C.back();
}
void push(const _Ty &x)
{
_C.push_back(x);
}
void pop()
{
_C.pop_back();
}
private:
vector<_Ty> _C;//若要使用list模拟只需要把vector改为list
};
}
二、queue
1.基本使用
注意这里的msdn有误,队列无top一说,队列的队头为front
代码演示:
void main()
{
queue<int> q;//容器适配器
for (int i = 1; i <= 10; ++i)//将1到10顺序入栈
{
q.push(i);
}
cout << "q.size = " << q.size() << endl;
while (!q.empty())//顺序出栈
{
int value = q.front();
q.pop();
cout << value << endl;
}
//无法通过迭代器访问
}
2.模拟实现
因为queue的接口中存在头删和尾插,因此使用vector来封装的效率太低,故可以借助list来模拟实现。
代码如下:
#include <list>
namespace LJL
{
template<class T>
class queue
{
public:
queue() {}
void push(const T& x) { _c.push_back(x); }
void pop() { _c.pop_front(); }
T& back() { return _c.back(); }
const T& back()const { return _c.back(); }
T& front() { return _c.front(); }
const T& front()const { return _c.front(); }
size_t size()const { return _c.size(); }
bool empty()const { return _c.empty(); }
private:
list<T> _c;
};
}
在系统中stack和queue是用容器双端队列deque来模拟的。
#include <deque>
namespace LJL
{
template<class _Ty,class Cont=deque<_Ty>>
class stack
{
public:
stack()
{}
~stack()
{}
public:
bool empty()const
{
return _C.empty();
}
size_t size()const
{
return _C.size();
}
_Ty& top()
{
return _C.back();
}
const _Ty& top()const
{
return _C.back();
}
void push(const _Ty &x)
{
_C.push_back(x);
}
void pop()
{
_C.pop_back();
}
private:
Cont _C;
};
template<class _Ty, class Cont=deque<_Ty>>
class queue
{
public:
queue()
{}
~queue()
{}
public:
bool empty()const
{
return _C.empty();
}
size_t size()const
{
return _C.size();
}
_Ty& front()
{
return _C.front();
}
_Ty& back()
{
return _C.back();
}
void pop()
{
_C.pop_front();
}
void push(const _Ty &x)
{
_C.push_back(x);
}
private:
Cont _C;
};
}
3.deque双端队列
是一种双开口的“连续”空间的数据结构(实际并不是连续的,而是由一段段连续的小空间拼接而成的,类似于一个动态的二维数组),可以再头尾两端进行插入和删除操作,且时间复杂度为O(1)而vector为O(n),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率较高,因为list不仅存储数据而且还需存储前后关系指针。
相对于普通queue而言,deque既可以尾插也可以头插,既可以头删也可以尾删。而queue只能尾插和头删。
代码演示:
void main()
{
deque<int> dq;
for (int i = 1; i <= 3; ++i)
{
dq.push_back(i);//尾插
}
for (int i = 3; i >= 1; --i)
{
dq.push_front(i);//头插
}
for (const auto & e : dq)
{
cout << e << " ";
}
cout << endl;
while (!dq.empty())
{
cout << dq.back() << endl;
dq.pop_back();
}
}
deque的缺陷:
不适合遍历,因为在遍历时,deque的迭代器要频繁检测其是否移动到某段小空间的边界,导致效率低下,目前对于queue的应用主要为stack和queue的底层数据结构。
以上是关于STL容器适配器之<queue>的主要内容,如果未能解决你的问题,请参考以下文章
C++STL之stackqueue的使用和模拟实现+优先级队列(附仿函数)+容器适配器详解
[C/C++]详解STL容器3--stackqueue和priority_queue的功能和模拟实现,deque和容器适配器的介绍