STL source code analysis-priority queue

Source: Internet
Author: User

The previous two articles introduced the source code implementation of vector and list in gcc4.8. This is the two most commonly used sequence containers in STL. In addition to containers, STL also provides a component called an adapter that uses containers for special operations, such as stack, queue, and priority queue, this article introduces the source code implementation of the priority queue of gcc4.8.

As the name suggests, priority queue is a queue with a priority. Therefore, elements must provide the <operator. Unlike vector and list, priority queue allows elements to be added, but only elements with the highest priority can be retrieved.

1. priority queue Definition

Priority queue does not have a base class

template<typename _Tp, typename _Sequence = vector<_Tp>,   typename _Compare  = less<typename _Sequence::value_type> >class priority_queue {    public:      typedef typename _Sequence::value_type                value_type;      typedef typename _Sequence::reference                 reference;      typedef typename _Sequence::const_reference           const_reference;      typedef typename _Sequence::size_type                 size_type;      typedef          _Sequence                            container_type;    protected:      _Sequence  c;      _Compare   comp;…...

Priority queue uses vector by default at the underlying layer, which contains two members. Vector C stores data. Comp is a function to compare the data size.

Ii. priority queue Construction Method

You can use vector to directly initialize priority queue, or any iterator or array pointer to initialize.

explicit      priority_queue(const _Compare& __x,                     const _Sequence& __s)      : c(__s), comp(__x)      { std::make_heap(c.begin(), c.end(), comp); }      explicit      priority_queue(const _Compare& __x = _Compare(),                     _Sequence&& __s = _Sequence())      : c(std::move(__s)), comp(__x)      { std::make_heap(c.begin(), c.end(), comp); }   template<typename _InputIterator>        priority_queue(_InputIterator __first, _InputIterator __last,                       const _Compare& __x,                       const _Sequence& __s)        : c(__s), comp(__x)        {          __glibcxx_requires_valid_range(__first, __last);          c.insert(c.end(), __first, __last);          std::make_heap(c.begin(), c.end(), comp);        } template<typename _InputIterator>        priority_queue(_InputIterator __first, _InputIterator __last,                       const _Compare& __x = _Compare(),                       _Sequence&& __s = _Sequence())        : c(std::move(__s)), comp(__x)        {          __glibcxx_requires_valid_range(__first, __last);          c.insert(c.end(), __first, __last);          std::make_heap(c.begin(), c.end(), comp);        }

Insert all elements into the priority queue and use make_heap to build the largest heap,

template<typename _RandomAccessIterator>    void make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)    { typedef typename iterator_traits<_RandomAccessIterator>::value_type          _ValueType;      typedef typename iterator_traits<_RandomAccessIterator>::difference_type          _DistanceType;      if (__last - __first < 2)        return;      const _DistanceType __len = __last - __first;      _DistanceType __parent = (__len - 2) / 2;      while (true)        {          _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));          std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value));          if (__parent == 0)            return;          __parent--;        }    }

_ Adjust_heap is a tracing process. the tracing process is performed one by one from the last non-leaf node so that it is the largest heap for the subtree of the root node.

template<typename _RandomAccessIterator, typename _Distance,           typename _Tp, typename _Compare>    void  __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,                  _Distance __len, _Tp __value, _Compare __comp)    {      const _Distance __topIndex = __holeIndex;      _Distance __secondChild = __holeIndex;      while (__secondChild < (__len - 1) / 2)        {          __secondChild = 2 * (__secondChild + 1);          if (__comp(*(__first + __secondChild),                     *(__first + (__secondChild - 1))))            __secondChild--;          *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));          __holeIndex = __secondChild;        }      if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)        {          __secondChild = 2 * (__secondChild + 1);          *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first                                                     + (__secondChild - 1)));          __holeIndex = __secondChild - 1;        }      std::__push_heap(__first, __holeIndex, __topIndex,                        _GLIBCXX_MOVE(__value), __comp);          }

3. priority queue element operations

Priority queue only has two main operations: Push and pop. New elements are added to push,

void push(const value_type& __x)      {        c.push_back(__x);        std::push_heap(c.begin(), c.end(), comp);      }

Put it in the last position, and then use push_heap to perform an upstream operation to move the inserted element to the appropriate position to ensure that the entire queue is still the largest heap.

template<typename _RandomAccessIterator, typename _Distance, typename _Tp>    void    __push_heap(_RandomAccessIterator __first,                _Distance __holeIndex, _Distance __topIndex, _Tp __value)    {      _Distance __parent = (__holeIndex - 1) / 2;      while (__holeIndex > __topIndex && *(__first + __parent) < __value)        {          *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));          __holeIndex = __parent;          __parent = (__holeIndex - 1) / 2;        }      *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);    }

The pop operation removes the heap top element,

Void POP ()

{

STD: pop_heap (C. Begin (), C. End (), comp );

C. pop_back ();

}

Because vector is used, it will be very costly to remove the first element and then make_heap. Here, we will first swap the first element with the last element, delete the last element, and then perform a tracing process from the first element to create a new largest heap.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.