容器适配器
stack、queue、priority_queue 都不支持任一种迭代器,它们都是容器适配器类型,stack是用vector/deque/list对象创建了一个先进后出容器;queue是用deque或list对象创建了一个先进先出容器;priority_queue是用vector/deque创建了一个排序队列,内部用二叉堆实现。
1、stack
stack的源码如下:
// TEMPLATE CLASS stack
template < class _Ty,
class _Container = deque<_Ty> >
class stack
{
// LIFO queue implemented with a container
public:
typedef _Container container_type;
typedef typename _Container::value_type value_type;
typedef typename _Container::size_type size_type;
typedef typename _Container::reference reference;
typedef typename _Container::const_reference const_reference;
stack()
: c()
{
// construct with empty container
}
explicit stack(const _Container &_Cont)
: c(_Cont)
{
// construct by copying specified container
}
bool empty() const
{
// test if stack is empty
return (c.empty());
}
size_type size() const
{
// test length of stack
return (c.size());
}
reference top()
{
// return last element of mutable stack
return (c.back());
}
const_reference top() const
{
// return last element of nonmutable stack
return (c.back());
}
void push(const value_type &_Val)
{
// insert element at end
c.push_back(_Val);
}
void pop()
{
// erase last element
c.pop_back();
}
const _Container &_Get_container() const
{
// get reference to container
return (c);
}
protected:
_Container c; // the underlying container
};
即有一个_Container 成员,默认是deque<_Ty> ,当然也可以传递vector, list 进去,只要支持push_back,pop_back 等接口。
【stack示例】
#include <iostream>
#include <vector>
#include <list>
#include <stack>
using namespace std;
int main(void)
{
stack< int, list<int> > s;
//add elements
for(int i = 0; i < 5; i++)
{
s.push(i);
}
//print all elements
while(!s.empty())
{
cout << s.top() << " ";
s.pop();
}
cout << endl;
return 0;
}
2、queue
queue的源码:
// TEMPLATE CLASS queue
template < class _Ty,
class _Container = deque<_Ty> >
class queue
{
// FIFO queue implemented with a container
public:
typedef _Container container_type;
typedef typename _Container::value_type value_type;
typedef typename _Container::size_type size_type;
typedef typename _Container::reference reference;
typedef typename _Container::const_reference const_reference;
queue()
: c()
{
// construct with empty container
}
explicit queue(const _Container &_Cont)
: c(_Cont)
{
// construct by copying specified container
}
bool empty() const
{
// test if queue is empty
return (c.empty());
}
size_type size() const
{
// return length of queue
return (c.size());
}
reference front()
{
// return first element of mutable queue
return (c.front());
}
const_reference front() const
{
// return first element of nonmutable queue
return (c.front());
}
reference back()
{
// return last element of mutable queue
return (c.back());
}
const_reference back() const
{
// return last element of nonmutable queue
return (c.back());
}
void push(const value_type &_Val)
{
// insert element at beginning
c.push_back(_Val);
}
void pop()
{
// erase element at end
c.pop_front();
}
const _Container &_Get_container() const
{
// get reference to container
return (c);
}
protected:
_Container c; // the underlying container
};
实现跟stack 是很类似的,只是queue不能用vector 实现,因为没有pop_front 接口。
【queue示例】
#include <iostream>
#include <vector>
#include <list>
#include <stack>
#include <queue>
using namespace std;
int main(void)
{
queue< int, list<int> > q;
//add elements
for(int i = 0; i < 5; i++)
{
q.push(i);
}
//print all elements
while(!q.empty())
{
cout << q.front() << " ";
q.pop();
}
cout << endl;
return 0;
}
3、priority_queue
priority_queue的源码:
// TEMPLATE CLASS priority_queue
template < class _Ty,
class _Container = vector<_Ty>,
class _Pr = less<typename _Container::value_type> >
class priority_queue
{
// priority queue implemented with a _Container
public:
typedef _Container container_type;
typedef typename _Container::value_type value_type;
typedef typename _Container::size_type size_type;
typedef typename _Container::reference reference;
typedef typename _Container::const_reference const_reference;
priority_queue()
: c(), comp()
{
// construct with empty container, default comparator
}
explicit priority_queue(const _Pr &_Pred)
: c(), comp(_Pred)
{
// construct with empty container, specified comparator
}
priority_queue(const _Pr &_Pred, const _Container &_Cont)
: c(_Cont), comp(_Pred)
{
// construct by copying specified container, comparator
make_heap(c.begin(), c.end(), comp);
}
template<class _Iter>
priority_queue(_Iter _First, _Iter _Last)
: c(_First, _Last), comp()
{
// construct by copying [_First, _Last), default comparator
make_heap(c.begin(), c.end(), comp);
}
template<class _Iter>
priority_queue(_Iter _First, _Iter _Last, const _Pr &_Pred)
: c(_First, _Last), comp(_Pred)
{
// construct by copying [_First, _Last), specified comparator
make_heap(c.begin(), c.end(), comp);
}
template<class _Iter>
priority_queue(_Iter _First, _Iter _Last, const _Pr &_Pred,
const _Container &_Cont)
: c(_Cont), comp(_Pred)
{
// construct by copying [_First, _Last), container, and comparator
c.insert(c.end(), _First, _Last);
make_heap(c.begin(), c.end(), comp);
}
bool empty() const
{
// test if queue is empty
return (c.empty());
}
size_type size() const
{
// return length of queue
return (c.size());
}
const_reference top() const
{
// return highest-priority element
return (c.front());
}
reference top()
{
// return mutable highest-priority element (retained)
return (c.front());
}
void push(const value_type &_Pred)
{
// insert value in priority order
c.push_back(_Pred);
push_heap(c.begin(), c.end(), comp);
}
void pop()
{
// erase highest-priority element
pop_heap(c.begin(), c.end(), comp);
c.pop_back();
}
protected:
_Container c; // the underlying container
_Pr comp; // the comparator functor
};
priority_queue 的实现稍微复杂一点,可以传递3个参数,而且有两个成员,comp 即自定义比较逻辑,默认是less<value_type>,在构造函数中调用make_heap函数构造二叉堆,comp 主要是用于构造二叉堆时的判别,如果是less 则构造大堆,如果传递greater 则构造小堆.
注意,priority_queue 不能用list 实现,因为list 只支持双向迭代器,而不支持随机迭代器。
【priority_queue示例】
#include <iostream>
#include <functional>
#include <vector>
#include <list>
#include <stack>
#include <queue>
using namespace std;
int main(void)
{
int a[] = {5, 1, 2, 4, 3};
//creat priority_queue and initialize priority_queue
//less<int>构造大堆
//greater<int>构造小堆
priority_queue < int, vector<int>, less<int> > q(a, a+5);
//print all elements
while(!q.empty())
{
cout << q.top() << " ";
q.pop();
}
cout << endl;
return 0;
}
在priority_queue的源码中用到了make_heap函数,下面举个例子说明make_heap 函数的用法:
#include <iostream>
#include <functional>
#include <algorithm>//sort()
#include <iterator>//ostream_iterator
#include <vector>
#include <list>
#include <stack>
#include <queue>
using namespace std;
int main(void)
{
int a[] = {5, 1, 2, 4, 3};
make_heap(a, a+5, less<int>());
//copy函数会将a,a+5区间的内的值拷贝至ostream_iterator中
//ostream_iterator< int >(cout, " ")是一个函数对象,其功能是依次打印ostream_iterator中的
//值,并以空格分割
copy(a, a+5, ostream_iterator< int >(cout, " "));
cout << endl;
sort(a, a+5);
//copy函数会将a,a+5区间的内的值拷贝至ostream_iterator中
copy(a, a+5, ostream_iterator< int >(cout, " "));
cout << endl;
return 0;
}
执行结果:
5 4 2 1 3
1 2 3 4 5
make_heap() 将容器的元素构造成二叉堆,传递的是less,即构造的是大堆,把大堆层序遍历的结果存入数组,再调用sort() 进行排序,内部调用的实际算法不一定,可以是堆排序、插入排序、选择排序等等,跟踪进去发现调用的是插入排序;当然也可以直接指定使用堆排序 sort_heap(调用者必须已经是堆了,也就是前面已经先调用了make_heap,而且大小堆类型得匹配),与make_heap 一样,第三个参数传递的都是函数对象的用法。sort 和 sort_heap 默认都是从小到大排序,除非重载的版本传递了第三个参数,如下,第三个参数可以是函数指针,也可以是函数对象:
// order heap by repeatedly popping, using operator<
template<class _RanIt> inline
void sort_heap(_RanIt _First, _RanIt _Last);
// order heap by repeatedly popping, using _Pred
template < class _RanIt,
class _Pr > inline
void sort_heap(_RanIt _First, _RanIt _Last, _Pr _Pred);