现在的位置: 首页 > 综合 > 正文

STL源码剖析 – 第4章 序列式容器 – priority_queue

2019年07月18日 ⁄ 综合 ⁄ 共 5013字 ⁄ 字号 评论关闭

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 )  

 

抱歉!评论已关闭.