目录
在stl中,有许多容器比如:string,vector,list,deque,map,set等等,
但是STL提供的两个容器queue和stack,其实都只是容器适配器而已,下面是关于queue,stack和deque的笔记:
一、stack:
1、栈的介绍:
stack(栈)是一种容器适配器,其特点是只能够在容器的一端进行元素的插入和提取操作。
2、栈的使用:
常用的栈的成员函数有
检查栈顶是否为空(empty())
返回栈中的元素个数(size())
返回栈顶元素的引用(top())
将元素val入栈(push())
将栈顶元素出栈(pop())
接下来,将上述的成员函数进行模拟实现:
3、栈的成员函数的模拟实现:
思路:
可采用两个模版参数,一个来控制数据类型,一个来控制底层结构,可以传vector或者list,在后面一个模版参数中可以加上一个缺省参数deque作为默认容器。
那么在stack的成员函数模拟实现中就可以直接调用容器的成员函数来实现。
namespace ppr
{
template<class T, class Container = deque<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();
}
private:
Container _con;
};
void stack_test1()
{
stack<int> st1;
st1.push(1);
st1.push(2);
st1.push(3);
st1.push(4);
cout << "此时栈顶元素是:" << st1.top() << endl;
cout << "该栈的结构为:" << endl;
while (!st1.empty())
{
cout << st1.top() << " ";
st1.pop();
}
cout << endl;
}
}
二、queue:
1、队列的介绍:
队列也是一种容器适配器,它是在容器的一端插入元素,在另外一端进行提取元素。
2、队列的使用:
常用的栈的成员函数有
检查队列是否为空(empty())
返回队列中的元素个数(size())
返回队列的队头元素的引用(front())
返回队列的队尾元素的引用(back())
将元素val入队列(push())
将栈顶元素出队列(pop())
接下来,将上述的成员函数进行模拟实现:
3、队列的模拟实现:
namespace ppr
{
template<class T, class Container = deque<T>>
class queue
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_front();
}
T& front()
{
return _con.front();
}
T& back()
{
return _con.back();
}
size_t size()
{
return _con.size();
}
bool empty()
{
return _con.empty();
}
private:
Container _con;
};
void queue_test1()
{
queue<int,list<int>> st1;
st1.push(10);
st1.push(20);
st1.push(30);
st1.push(40);
cout << "front是" << st1.front() << endl;
cout << "back是" << st1.back() << endl;
cout << "该队列的结构为:" << endl;
while (!st1.empty())
{
cout << st1.front() << " ";
st1.pop();
}
cout << endl;
}
}
三、deque:
vector能够支持下标随机访问,但是存在扩容问题,只能中部和头部插入效率问题(毕竟要移动数据)
list能够在任意位置插入和删除都可以,但不支持下标随机访问,
那么后来有大佬搞了deque,
deque:
是一种双端队列(double ended queue):可以在头尾两端进行插入和删除,比vector的头插效率高,毕竟不需要移动元素,比list空间利用率高。
deque的底层结构:
deque是由一个中控数组(指针数组),每个指针指向一块相等大小的空间。数据就插入在这些被指向的空间中,如果空间不够需要扩容,就从中控数组中扩容,然后新的数组的值再指向一块新的空间。如果中控数组也满了就扩容中控数组。
接下来看看deque的成员函数:
通过下图可以看到,deque基本涵盖了vector和list的所有部分,使用起来几乎没有差异。
deque和vector和list的区别:
deque和vector:
极大地缓解了扩容/头插/头删问题,扩容时也不需要移动元素,效率就高
deque和list:
可以支持下标随机访问,空间利用率高
根据以上的特点,deque就特别适合做栈和队列的默认容器。
deque致命缺陷:
不适合遍历,在遍历的时候会频繁地去检查所要找的元素在哪一个空间中导致效率低,
因此大多数时候都考虑使用vector和list。