【C++】容器适配器
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
文章目录
一. 什么是适配器?什么是容器适配器?
- 适配器是一种设计模式设计模式是一套被反复使用的多数人知晓的经过分类编目的代码设计经验的总结该种模式将一个类的接口转换成用户需要的另外一个接口。
举个例子在日常生活中当手机没电了我们需要给手机充电给手机充电的方式很多可以插到电源上也可以用充电宝还可以直接连着电脑充。而我们并不关心用什么给它充电我们关心的只是能否给手机充上电。适配器充当的角色就是 给手机充电的接口它会将不同大小的电压转化成适合给手机充电的电压。容器适配器的概念可以结合这个例子理解它以 某种容器作为底层结构改变其接口使它符合该容器的特性。
- 容器适配器以某种已有的既定容器作为底层结构在其基础上进一步地进行封装接口函数。使其可以满足某种特性。
下面将介绍三个用到容器适配器的结构:stack栈,queue队列,priority_queue优先级队列,通过这三个结构我们可以更好的理解容器适配器的用途。
二.理解容器适配器
- STL的六大组件
我们可以看出虽然stackqueuepriority_queue中也可以存放数据但在STL中并没有将其划分在容器的行列而是将其称为容器配接器这是因为stackqueuepriority_queue只是对其它容器的接口进行了包装STL中stack和queue默认使用deque,priority_queue默认使用vector作为容器。我们现在来看看它们的底层接口和实现
stack的模拟实现
知道了容器适配器后stack的模拟实现就简单了我们只需要调用指定容器deque的各个成员函数即可实现stack的各个函数接口。
底层实现代码如下stack底层利用deque双端队列进行包装需要更改成多参数模板最便利的一点就是stack的底层函数的实现可以直接调用容器的函数接口不需要自己再一步步实现。
namespace nn //命名空间域防止命名冲突
{
//多参数模板
template<class T, class Container = std::deque<T>>//可以明显看出stack配接器的底层容器是deque双端队列后面会介绍
class stack
{
public:
//元素入栈
void push(const T& x)
{
_con.push_back(x);
}
//元素出栈
void pop()
{
_con.pop_back();
}
//获取栈顶元素
T& top()
{
return _con.back();
}
const T& top() const//const修饰
{
return _con.back();
}
//获取栈中有效元素个数
size_t size() const
{
return _con.size();
}
//判断栈是否为空
bool empty() const
{
return _con.empty();
}
//交换两个栈中的数据
void swap(stack<T, Container>& st)//注意stack<T,Container>才是类型,加引用别名减少拷贝
{
_con.swap(st._con);//调用deque的算法swap
}
private:
//deque<T> _con底层
Container _con;//将一个类的接口转换成用户需要的另一种接口即利用deque容器转换成stack配接器
};
}
queue的模拟实现
同样的方式我们也是通过调用所指定容器的各个成员函数来实现queue的。
底层实现代码如下
namespace nn //防止命名冲突
{
template<class T, class Container = std::deque<T>>
class queue
{
public:
//队尾入队列
void push(const T& x)
{
_con.push_back(x);
}
//队头出队列
void pop()
{
_con.pop_front();
}
//获取队头元素
T& front()
{
return _con.front();
}
const T& front() const
{
return _con.front();
}
//获取队尾元素
T& back()
{
return _con.back();
}
const T& back() const
{
return _con.back();
}
//获取队列中有效元素个数
size_t size() const
{
return _con.size();
}
//判断队列是否为空
bool empty() const
{
return _con.empty();
}
//交换两个队列中的数据
void swap(queue<T, Container>& q)
{
_con.swap(q._con);
}
private:
Container _con;//deque<T> _con;
};
}
思考stack 和 queue 是否存在迭代器?
stack 和 queue 都不具备迭代器, 因为两者都不具备遍历走访功能所以自然不需要设计迭代器
stack 和 queue可以以哪些容器作为底层容器?
实际上stack使用vector作为底层容器也是可以的queue使用deque双端队列+list带头双向循环链表作为底层容器也是可以的。
但是deque在设计上相比于list和vector作为stackqueue的底层结构更优。
底层容器如何传进去?
作为模板参数传入template<class T,class Container = deque<T>>
,用了默认参数缺省参数