STL(八)—— stack和queue的模拟
目录
- 一、容器适配器
- 二、stack的模拟实现
- 三、queue的模拟实现
一、容器适配器
stack和queue有一点需要注意的是,虽然stack和queue中也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和queue只是对其他容器的接口进行了包装,STL中stack和queue默认使用deque容器。
在stack和queue的类模板声明当中我们就可以看到,它们的模板参数有两个,第一个是stack和queue当中所存储的元素类型,而另一个就是指定使用的容器类型。只不过当我们不指定使用何种容器的情况下,stack和queue都默认使用deque作为指定容器。
简单理解: 学过数据结构后我们都知道,stack和queue既可以使用顺序表实现,也可以使用链表实现。在这里我们若是定义一个stack,并指定使用vector容器,则定义出来的stack实际上就是对vector容器进行了包装
二、stack的模拟实现
知道了容器适配器后,stack的模拟实现就很简单,只需要调用所指定容器的各个成员函数即可实现stack的各个函数接口。
成员函数 | 函数作用 | 实现方法 |
---|---|---|
push | 元素入栈 | 调用所指定容器的push_back |
pop | 元素出栈 | 调用所指定容器的pop_back |
top | 获取栈顶元素 | 调用所指定容器的back |
size | 获取栈中有效元素个数 | 调用所指定容器的size |
empty | 判断栈是否为空 | 调用所指定容器的empty |
swap | 交换两个栈中的数据 | 调用所指定容器的swap |
模拟如下
#pragma once
#include<vector>
#include<list>
namespace ling
{
//容器适配器
template<class T,class Container = std::vector<T>>
class stack
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
T& top()
{
return _con.back();
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty;
}
void swap(stack<T, Container>& st)
{
_con.swap(st._con);
}
private:
Container _con;
};
}
自定义类型并不需要默认成员函数如构造函数、拷贝构造、析构函数。
三、queue的模拟实现
同样的方式,我们也是通过调用所指定容器的各个成员函数来实现queue的
成员函数 | 函数作用 | 实现方法 |
---|---|---|
push | 队尾入队列 | 调用所指定容器的push_back |
pop | 队头出队列 | 调用所指定容器的pop_front |
front | 获取队头元素 | 调用所指定容器的front |
back | 获取队尾元素 | 调用所指定容器的back |
size | 获取队列中有效元素个数 | 调用所指定容器的size |
empty | 判断队列是否为空 | 调用所指定容器的empty |
swap | 交换两个队列中的数据 | 调用所指定容器的swap |
模拟如下
#pragma once
#include<vector>
#include<list>
namespace ling
{ //vector在这里不适合
template<class T, class Container = std::list<T>>
class stack
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
//_con.pop_front(); 如果要适配vector就不能直接写头删,因为vector没有提供头删函数
_con.erase(_con.begin()); //通用
}
T& front()
{
return _con.front();
}
T& back()
{
return _con.back();
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty;
}
private:
Container _con;
};
}
可见它们是很类似的