1.deque概述
deque是双端队列,daque和vector的差异,一在于daque允许常数时间内对起头端进行元素的插入或移除操作,二在于deque没有所谓的容量(capacity)的概念。因为它是动态的以分段连续空间组合而成,随时增加一段新的空间并连接起来。
deque的内部结构很复杂,因此其迭代器结构也复杂。虽然其迭代器是Random Access Iterator但是相比于vector的迭代器在运用sort算法的时候,效率是差很多的。所以对deque进行排序可以将deque复制(assign)进一个vector然后对此vector进行排序之后,再将元素复制回deque。一般对deque排序用的也不多。
2.deque的内部数据结构
deque的内部数据结构比较复杂,这里略过。
3.deque的操作
对于STL中的容器而言,push_back,pop_back,push,pop操作都是没有返回值的。相应的对于vector,list,deque,queue就有front和back操作来返回第一个和最后一个元素。对于stack则是top。
deque中的操作要注意的就是erase虽然也是用copy函数,但是其删除了最后的冗余节点,这么做是正常的行为,vector是不正常的,因为其要保留空间(reverse功能也是这个设计目的)。
4.stack
stack是STL中的适配器,其默认的底层结构就是deque,代码很简洁,如下:
class stack {
friend bool operator== __STL_NULL_TMPL_ARGS (const stack&, const stack&);
friend bool operator< __STL_NULL_TMPL_ARGS (const stack&, const stack&);
public:
typedef typename Sequence::value_type value_type;
typedef typename Sequence::size_type size_type;
typedef typename Sequence::reference reference;
typedef typename Sequence::const_reference const_reference;
protected:
Sequence c; // 底层容器,默认为deque,
public:
// 以下完全利用 Sequence c 的操作,完成 stack 的操作。
bool empty() const { return c.empty(); }
size_type size() const { return c.size(); }
reference top() { return c.back(); }
const_reference top() const { return c.back(); }
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_back(); }
};
template <class T, class Sequence>
bool operator==(const stack<T, Sequence>& x, const stack<T, Sequence>& y) {
return x.c == y.c;
}
template <class T, class Sequence>
bool operator<(const stack<T, Sequence>& x, const stack<T, Sequence>& y) {
return x.c < y.c;
}
其中需要注意的就是top和pop。pop是没有返回值的!!!!!!另外stack是适配器,是没有迭代器的。所以显然算法库是无法用在stack上的,另外要注意的是swap、assign不适用于stack。
5.queue
queue是单端队列,也是STL中的适配器,其底层结构是deque。
class queue
{
friend bool operator== __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);
friend bool operator< __STL_NULL_TMPL_ARGS (const queue& x, const queue& y);
public:
typedef typename Sequence::value_type value_type;
typedef typename Sequence::size_type size_type;
typedef typename Sequence::reference reference;
typedef typename Sequence::const_reference const_reference;
protected:
Sequence c; // 底层容器,默认为deque
public:
// 以下完全利用 Sequence c 的操作,完成 queue 的操作。
bool empty() const { return c.empty(); }
size_type size() const { return c.size(); }
reference front() { return c.front(); }
const_reference front() const { return c.front(); }
reference back() { return c.back(); }
const_reference back() const { return c.back(); }
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_front(); }
};
template <class T, class Sequence>
bool operator==(const queue<T, Sequence>& x, const queue<T, Sequence>& y) {
return x.c == y.c;
}
template <class T, class Sequence>
bool operator<(const queue<T, Sequence>& x, const queue<T, Sequence>& y) {
return x.c < y.c;
}
注意点和stack类似,pop是没有返回值的,查看两段元素是用back和front。另外同样是适配器,所以没有迭代器,没有swap,assgin操作。
6.priority_queue
priority_queue是优先级队列,是以堆算法为基础的。堆是一种隐式数据结构,所以priority_queue的底层结构默认是vector。
priority内部用的是对算法,但是接口表现上是队列的接口。代码很简单,如下:
class priority_queue
{
public:
typedef typename Sequence::value_type value_type;
typedef typename Sequence::size_type size_type;
typedef typename Sequence::reference reference;
typedef typename Sequence::const_reference const_reference;
protected:
Sequence c; // 底层容器
Compare comp; // 元素大小比较标准
public:
priority_queue() : c() {}
explicit priority_queue(const Compare& x) : c(), comp(x) {}
//priority_queue的任何一个构造函数都会调用make_heap来构建隐式堆结构
#ifdef __STL_MEMBER_TEMPLATES
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last, const Compare& x)
: c(first, last), comp(x) { make_heap(c.begin(), c.end(), comp); }
template <class InputIterator>
priority_queue(InputIterator first, InputIterator last)
: c(first, last) { make_heap(c.begin(), c.end(), comp); }
#else /* __STL_MEMBER_TEMPLATES */
priority_queue(const value_type* first, const value_type* last,
const Compare& x) : c(first, last), comp(x) {
make_heap(c.begin(), c.end(), comp);
}
priority_queue(const value_type* first, const value_type* last)
: c(first, last) { make_heap(c.begin(), c.end(), comp); }
#endif /* __STL_MEMBER_TEMPLATES */
bool empty() const { return c.empty(); }
size_type size() const { return c.size(); }
const_reference top() const { return c.front(); }
void push(const value_type& x) {
__STL_TRY {
c.push_back(x);
push_heap(c.begin(), c.end(), comp); // push_heap 是泛型演算法
}
__STL_UNWIND(c.clear());
}
void pop() {
__STL_TRY {
pop_heap(c.begin(), c.end(), comp);
c.pop_back();
}
__STL_UNWIND(c.clear());
}
};
要注意的是优先级队列是单端队列,但是和queue的接口不同,priority_queue只有top接口。