4.8.1 priority_queue概述
priority_queue(优先队列)是拥有优先级的queue,不过它容器内的元素并不是根据加入顺序排列,而是根据用户定义的优先级进行排列。priority_queue只能在队列尾部加入元素,在头部取出元素。不能遍历容器,因此不需要自己设置迭代器。在SGI STL的源码<stl_queue.h>的class priority_queue设计中,它是基于某种容器作为底部结构的,默认容器是vector容器,用户也可以自己指定容器的类型。缺省情况下priority_queue利用max-heap完成,后者是一个以vector表现的完全二叉树。map-heap可以满足priority_queue所需要的“依权值高低自动递增排序”的特性。
4.8.2 priority_queue源码剖析
由于priority_queue完全以底部容器为根据,再加上heap处理规则,所以其实现非常简单。缺省情况下是以vector为底部容器。priority_queue也是以底部容器完成其所有操作,所以被归类为容器配接器。
下面给出源码剖析:
template <class _Tp,
class _Sequence __STL_DEPENDENT_DEFAULT_TMPL(vector<_Tp>),
class _Compare
__STL_DEPENDENT_DEFAULT_TMPL(less<typename _Sequence::value_type>) >
class priority_queue {
// requirements:
__STL_CLASS_REQUIRES(_Tp, _Assignable);
__STL_CLASS_REQUIRES(_Sequence, _Sequence);
__STL_CLASS_REQUIRES(_Sequence, _RandomAccessContainer);
typedef typename _Sequence::value_type _Sequence_value_type;
__STL_CLASS_REQUIRES_SAME_TYPE(_Tp, _Sequence_value_type);
__STL_CLASS_BINARY_FUNCTION_CHECK(_Compare, bool, _Tp, _Tp);
public:
// priority_queue仅支持对头部和尾部的操作, 所以不定义STL要求的
// pointer, iterator, difference_type
typedef typename _Sequence::value_type value_type;
typedef typename _Sequence::size_type size_type;
typedef _Sequence container_type;
typedef typename _Sequence::reference reference;
typedef typename _Sequence::const_reference const_reference;
protected:
_Sequence c;//底层容器,默认为vector,用户可自行指定容器类型
_Compare comp;//优先级决策方式
public:
//***********************************************************
//* 构造函数
//* priority_queue()
//* explicit priority_queue(const Compare& __x)
//* explicit priority_queue (const Compare& comp = Compare(),
//* const Container& ctnr = Container());
//* template <class InputIterator>
//* priority_queue (InputIterator first, InputIterator last,
//* const Compare& comp = Compare(),
//* const Container& ctnr = Container());
//***********************************************************
priority_queue() : c() {}
explicit priority_queue(const _Compare& __x) : c(), comp(__x) {}
priority_queue(const _Compare& __x, const _Sequence& __s)
: c(__s), comp(__x)
{ make_heap(c.begin(), c.end(), comp); }
#ifdef __STL_MEMBER_TEMPLATES
template <class _InputIterator>
priority_queue(_InputIterator __first, _InputIterator __last)
: c(__first, __last) { make_heap(c.begin(), c.end(), comp); }
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,
const _Compare& __x, const _Sequence& __s)
: c(__s), comp(__x)
{
c.insert(c.end(), __first, __last);
make_heap(c.begin(), c.end(), comp);
}
#else /* __STL_MEMBER_TEMPLATES */
priority_queue(const value_type* __first, const value_type* __last)
: c(__first, __last) { make_heap(c.begin(), c.end(), comp); }
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,
const _Compare& __x, const _Sequence& __c)
: c(__c), comp(__x)
{
c.insert(c.end(), __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);
}
__STL_UNWIND(c.clear());
}
//弹出优先级最高的元素
void pop() {
__STL_TRY {
pop_heap(c.begin(), c.end(), comp);
c.pop_back();
}
__STL_UNWIND(c.clear());
}
};
// no equality is provided
__STL_END_NAMESPACE
#endif /* __SGI_STL_INTERNAL_QUEUE_H */
// Local Variables:
// mode:C++
// End:
举例说明该容器的使用:
// constructing priority queues
#include <iostream> // std::cout
#include <queue> // std::priority_queue
#include <vector> // std::vector
#include <functional> // std::greater
class mycomparison
{
bool reverse;
public:
mycomparison(const bool& revparam=false)
{reverse=revparam;}
bool operator() (const int& lhs, const int&rhs) const
{
if (reverse) return (lhs>rhs);
else return (lhs<rhs);
}
};
int main ()
{
int myints[]= {10,60,50,20};
std::priority_queue<int> first;
std::priority_queue<int> second (myints,myints+4);
std::priority_queue<int, std::vector<int>, std::greater<int> >
third (myints,myints+4);
std::cout << "third = ( ";
while ( !third.empty( ) )
{
std::cout << third.top( ) << " ";
third.pop( );
}
std::cout << ")" << std::endl;
// using mycomparison:
typedef std::priority_queue<int,std::vector<int>,mycomparison> mypq_type;
mypq_type fourth (myints,myints+4); // less-than comparison
mypq_type fifth (mycomparison(true)); // greater-than comparison
std::cout << "fourth = ( ";
while ( !fourth.empty( ) )
{
std::cout << fourth.top( ) << " ";
fourth.pop( );
}
std::cout << ")" << std::endl;
std::cout << "fifth = ( ";
while ( !fifth.empty( ) )
{
std::cout << fifth.top( ) << " ";
fifth.pop( );
}
std::cout << ")" << std::endl;
for (int i = 0; i < 5; i++)
{
fifth.push(i*10);
}
std::cout <<"after push the elements,fifth size is :"<<fifth.size()<<std::endl;
std::cout << "after push the elements,fifth = ( ";
while ( !fifth.empty( ) )
{
std::cout << fifth.top( ) << " ";
fifth.pop( );
}
std::cout << ")" << std::endl;
system("pause");
return 0;
}
third = ( 10 20 50 60 )
fourth = ( 60 50 20 10 )
fifth = ( )
after push the elements,fifth size is :5
after push the elements,fifth = ( 0 10 20 30 40 )