除了vector,list,deque等常用的容器,还有根据这些常用的容器进行改造来满足特殊要求的容器,这些特殊容器的行为和常用容器很相近,也称为容器适配器。
常用的容器适配器有三个,分别是stack(栈)、queue(队列)、priority_queue(优先队列)
1.stack(栈)
使用stack时,要添加头文件#include<stack>
stack是先进后出,后进先出,结构如下
stack(栈)默认是通过deque来进行改造实现的
template <class T, class Container = deque<T> > class stack;
class T表示的是存储的元素类型,class Container = deque<T>中也存在T,说明stack中存储的元素类型必须和Container中存储的元素类型一致。
Container用于实现stack的底层容器类型,Container必须是顺序容器且必须提供三个成员函数:back(),push_back(),pop_back(),所以,基于上述要求,vector和list也是符合Container条件的顺序容器,只不过如果没有指明Container的类型,那么默认采用deque作为stack的底层实现
stack采用deque为底层实现时的内部接口如下
1.1 stack(栈)常用的构造函数
explicit stack (const container_type& ctnr);//构造函数,指定底层具体的具体实现
explicit stack( const container_type& ctnr = Container() );//默认构造函数,底层实现默认是deque
stack( const stack& other );//拷贝构造函数
其中container_type表示stack底层实现的具体容器类型,为list,vector和deque三选一,默认是deque
示例
void stackinit()
{
vector<double> d={1,2,3,4};
stack<double, vector<double>> st(d);//底层实现为vector,将d中的元素压栈
while(!st.empty()) {
cout<<st.top()<<endl;//因为先进后出,所以倒序输出
st.pop();
}
}
注意:底层实现容器中的数据类型必须和stack对象的数据类型一致,stack<double, vector<double>>数据类型一致,stack<double, vector<float>>数据类型不一致
1.2 添加和删除
void pop();//从stack对象中删除一个元素
void push (const value_type& val);//向stack对象中添加一个元素
1.3 top函数返回栈顶元素,同时也可以作为左值修改栈顶元素
reference& top();
const_reference& top() const;
bool empty() const;
size_type size() const;
示例
void stackpushpop()
{
stack<int> st;
for (int i=0;i<10;++i) {
st.push(i);
}
cout<<st.size();
while(!st.empty()) {
cout<<st.top()<<endl;
st.pop();
}
cout<<st.size();
}
1.4 交换操作
void swap (stack& x) noexcept
template <class T, class Container>
void swap (stack<T,Container>& x, stack<T,Container>& y) noexcept(noexcept(x.swap(y)));
noexcept(noexcept(x.swap(y)))表示在交换的过程中不会出现异常,如果出现异常,程序直接退出
示例
void stackswap()
{
stack<int> st1;
for (int i=0;i<10;++i) {
st1.push(i);
}
stack<int> st2;
for (int i=0;i<5;++i) {
st2.push(i);
}
st1.swap(st2);
//swap(st1,st2);
while(!st1.empty()) {
cout<<st1.top();
st1.pop();
}
cout<<endl;
while(!st2.empty()) {
cout<<st2.top();
st2.pop();
}
}
2.queue(队列)
使用queue时,要添加头文件#include<queue>
queue(队列)是先进先出,结构如下
queue默认是通过deque来进行改造实现的
template <class T, class Container = deque<T> > class queue;
class T表示的是存储的元素类型,class Container = deque<T>中也存在T,说明queue中存储的元素类型必须和Container中存储的元素类型一致。
Container用于实现queue的底层容器类型,Container必须是顺序容器且必须提供4个成员函数:front(),back(),push_back(),pop_front(),所以,基于上述要求,list也是符合Container条件的顺序容器,只不过如果没有指明Container的类型,那么默认采用deque作为queue的底层实现
queue采用deque为底层实现时的内部接口如下
2.1 queue的常用构造函数
explicit queue (const container_type& ctnr = container_type());
explicit queue (const container_type& ctnr);
queue( const queue& other );
示意参照stack
示例
void queueinit()
{
list<int> l={1,2,3,4,5};
queue<int, list<int>> q(l);//底层实现的容器是list
while(!q.empty()) {
cout<<q.front()<<endl;
q.pop();
}
}
因为先进先出,所以打印头元素时会顺序打印
2.2 添加和删除
void pop();//删除队列头的元素
void push (const value_type& val);//添加元素到队列尾
使用方法同stack
2.3 back和front
reference& back();
const_reference& back() const;
reference& front();
const_reference& front() const;
bool empty() const;
size_type size() const;
因为队列是双端的,所以stack的top变成了back和front,这两个成员分别返回或修改队列两端的数据
使用方法同vector,string,list和deque
2.4 交换
void swap (queue& x) noexcept
template <class T, class Container>
void swap (queue<T,Container>& x, queue<T,Container>& y) noexcept(noexcept(x.swap(y)));
使用方法同stack
3.priority_queue(优先队列)
priority_queue是一种特别的queue,priority_queue中的元素会按照优先级依次被排列起来,默认按照升序排列,可以指定其他排列方式
priority_queue也在头文件#include<queue>中
priority_queue的结构如下
priority_queue默认是通过vector来进行改造实现的
template <class T, class Container = vector<T>, class Compare = less<typename Container::value_type> > class priority_queue;
其中Compare是优先级的规则,用函数指针或函数对象的类型来表示,该类型的对象必须是严格弱序的
Container用于实现priority_queue的底层容器类型,Container必须是顺序容器且必须提供3个成员函数:front(),push_back(),pop_back(),且Container的迭代器类型必须是随机迭代器。所以,基于上述要求,deque也是符合Container条件的顺序容器,只不过如果没有指明Container的类型,那么默认采用vector作为priority_queue的底层实现
3.1 priority_queue的常用构造函数
explicit priority_queue(const Compare& compare = Compare(), const Container& cont = Container());//默认构造函数
priority_queue( const Compare& compare, const Container& cont );//一般构造函数
priority_queue( const priority_queue& other );//拷贝构造函数
template< class InputIt >
priority_queue(InputIt first, InputIt last, const Compare& compare, const Container& cont);//接受范围迭代器的构造函数
示例1
bool comp(int a, int b) {return a>b;}
void priority_queueinit()
{
deque<int> d={1,3,5,2,4,6};
priority_queue<int, deque<int>, bool(*)(int, int)> pq(comp, d);//第三个模板参数类型是一个函数指针,comp和函数指针的类型一致
while(!pq.empty()) {
cout<<pq.top()<<endl;
pq.pop();
}
}
因为降序排列,所以升序输出
示例2
bool comp(int a, int b) {return a>b;}
void priority_queueinit()
{
deque<int> d={1,3,5,2,4,6};
priority_queue<int, deque<int>, bool(*)(int, int)> pq(++d.begin(), --d.end(),comp, d);
//将++d.begin(), --d.end()范围内的元素和d中的元素按照comp规定的优先级进行排列
while(!pq.empty()) {
cout<<pq.top()<<endl;
pq.pop();
}
}
3.2 添加和删除
void pop();//从优先队列头删除元素
void push (const value_type& val);//从优先队列尾添加元素
同stack和queue
3.3 访问
const_reference top() const;//获取优先级最高的元素
priority_queue不能像queue那样访问队列头和尾,只能访问优先级最高的元素,同stack
bool empty() const;
size_type size() const;
同stack和queue
3.4 交换
void swap (priority_queue& x)
template <class T, class Container, class Compare>
void swap (priority_queue<T,Container,Compare>& x, priority_queue<T,Container,Compare>& y) noexcept(noexcept(x.swap(y)));
同stack和queue
最后,上述三个容器适配器都是只能在容器适配器的两端或者一端进行操作,不能操作适配器中间的元素,所以上述三个容器适配器不支持迭代器
参考
《C++ Primer》
《C++标准库》
http://www.cplusplus.com/reference/stack/stack/
http://www.cplusplus.com/reference/queue/queue/
http://www.cplusplus.com/reference/queue/priority_queue/
https://zh.cppreference.com/w/cpp/container/stack
https://zh.cppreference.com/w/cpp/container/queue
https://zh.cppreference.com/w/cpp/container/priority_queue
https://www.cnblogs.com/sword03/p/10020344.html
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出