STL源码剖析——priority_queue

来源:互联网 发布:淘宝分享有礼在哪找 编辑:程序博客网 时间:2024/05/17 12:00

一、概述


priority_queue,首先它是一个queue,即只允许在低端加入元素,并从顶端取出元素,除此之外别无其他存取元素的途径(故priority_queue不提供遍历功能,也不提供迭代器);再次它具有priority,即queue中的元素具有一定的priority:其内的元素自动依照元素的权值排列,权值最高者(也就是数值最高),排在最前面。

:在queue并非是依照严格的权值递减的顺序排列,而是每次保持顶端(对头)元素为queue中权值最高的元素(其内部采用heap实现(默认是max heap))。


二、实现


由于priority_queue完全以底部容器为根据,在加上heap处理规则,所以其实现较简单,且缺省情况下以vector底部容器

联系适配器(adapter)的定义:具有这种【修改某物接口,形成另一种风貌】之性质者,称为adapter。因为,STL priority_queue被归类为:Container adapter 


其SGI(Silicon Graphics Computer Systems, Inc.) STL中的priority_queue的源码如下:






  /*  *  * Copyright (c) 1994  * Hewlett-Packard Company  *  * Permission to use, copy, modify, distribute and sell this software  * and its documentation for any purpose is hereby granted without fee,  * provided that the above copyright notice appear in all copies and  * that both that copyright notice and this permission notice appear  * in supporting documentation.  Hewlett-Packard Company makes no  * representations about the suitability of this software for any  * purpose.  It is provided "as is" without express or implied warranty.  *  *  * Copyright (c) 1996,1997  * Silicon Graphics Computer Systems, Inc.  *  * Permission to use, copy, modify, distribute and sell this software  * and its documentation for any purpose is hereby granted without fee,  * provided that the above copyright notice appear in all copies and  * that both that copyright notice and this permission notice appear  * in supporting documentation.  Silicon Graphics makes no  * representations about the suitability of this software for any  * purpose.  It is provided "as is" without express or implied warranty.  */    /* NOTE: This is an internal header file, included by other STL headers.  *   You should not attempt to use it directly.  */    #ifndef __SGI_STL_INTERNAL_QUEUE_H  #define __SGI_STL_INTERNAL_QUEUE_H    __STL_BEGIN_NAMESPACE    // 如果编译器不能根据前面模板参数推导出后面使用的默认参数类型,  // 那么就需要手工指定, 本实作queue内部容器默认使用deque  // 由于queue要求在队尾追加元素, 在队头获取和移除元素  // 所以非常适合使用deque  #ifndef __STL_LIMITED_DEFAULT_TEMPLATES  template <class T, class Sequence = deque<T> >  #else  template <class T, class Sequence>  #endif  class queue  {    // 讲解见<stl_pair.h>中的运算符剖析    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:    // 由于queue仅支持对队头和队尾的操作, 所以不定义STL要求的    // pointer, iterator, difference_type    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;   // 这个是我们实际维护的容器    public:      // 这些是STL queue的标准接口, 都调用容器的成员函数进行实现    // 其接口和stack实现很接近, 参考<stl_stack.h>    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(); }  };    // 详细讲解见<stl_pair.h>  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;  }    #ifndef __STL_LIMITED_DEFAULT_TEMPLATES  template <class T, class Sequence = vector<T>,            class Compare = less<typename Sequence::value_type> >  #else  template <class T, class Sequence, class Compare>  #endif  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) {}    // 使用[first, last)区间构造priority_queue  #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 */      // STL priority_queue标准接口    bool empty() const { return c.empty(); }    size_type size() const { return c.size(); }      // 返回优先级最高的元素    const_reference top() const { return c.front(); }      // 插入元素, 并调整heap    void push(const value_type& x)    {      __STL_TRY {        c.push_back(x);        // 详细分析见<stl_heap.h>        push_heap(c.begin(), c.end(), comp);      }      __STL_UNWIND(c.clear());    }      // 弹出优先级最高的元素    void pop() {      __STL_TRY {        // 详细分析见<stl_heap.h>        pop_heap(c.begin(), c.end(), comp);        c.pop_back();      }      __STL_UNWIND(c.clear());    }  };    // 不提供比较操作    __STL_END_NAMESPACE    #endif /* __SGI_STL_INTERNAL_QUEUE_H */    // Local Variables:  // mode:C++  // End:  


class Compare = less<typename Sequeue::value_type>中的less对应大顶堆,即用parent与holeIndex值比较,若小于则percolate up:调整洞号,向上提升值父节点。---见《STL源码剖析》P175。


三、测试实例


#include <iostream>#include <queue>using namespace std;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};    priority_queue<int> first;    priority_queue<int> second(myInts, myInts+4);    cout << "second size: " << second.size() << endl;    cout << "second top: " << second.top() << endl;    second.push(100);    cout << "second top: " << second.top() << endl;    priority_queue<int, vector<int>, greater<int> > third(myInts, myInts+4);    cout << "third size: " << third.size() << endl;    cout << "third top: " << third.top() << endl;    third.push(100);    cout << "third top: " << third.top() << endl;    //using myComparison    priority_queue<int, vector<int>, myComparison > fourth;    typedef priority_queue<int, vector<int>, myComparison> myPq_type;    myPq_type fifth(myComparison() );    myPq_type sixth(myInts, myInts+4, myComparison(true) );    cout << "sixth top: " << sixth.top() << endl;    sixth.pop();    cout << "sixth top: " << sixth.top() << endl;    return 0;}




0 0
原创粉丝点击