STL源码结构解析之Stack,Queue,Priority_Queue

这里的STL源码结构解析的版本均是G++ 4.4.4。该源代码可以在gun中下载,如果有安装linux,一个STL源码存储再/usr/include/c++/目录下。

文章先对STL中的stack,queue,priority_queue的异同点进行解析,接着分别解析了stack,queue,priority_queue的源码结构实现方式。

 

stack,queue,priority_queue的相同点

之所以把stack,queue,priority_queue三者放在一起,是因为这三种容器再STL中均属于特殊容器。他们都具有如下特征:

  1. 它们均是为满足特定需求而建立的容器。stack是为了满足FILO,queue是为了满足FIFO,priority_queue则是为了满足优先级高的元素先出队列。
  2. 它们均具有一组含义非常明确的函数接口,比如stack的top,pop, push分别表示获取栈顶元素,出栈和入栈,queue的front,back, pop, push分别表示获取队列首元素,队列尾元素,出队列和入队列。
  3. 它们均不是标准的STL容器,却都是以标准STL容器为基础。stack和queue默认是在deque的基础上封装的,priority_queue默认是在vector的基础上封装出来的。stack和queue的基础容器之所以选择deque而不选择vector等容器,是因为deque在删除元素的时候可以释放空间,同时在重新申请空间的时候无需拷贝所有元素。
  4. 它们均对基础容器有一定的要求,这个要求是由他们满足的需求确定的。比如stack需要从栈顶进出元素和获取栈顶元素,它的基础容器则需要提供back(), push_back(), pop_back()的函数。同理queue的基础容器需要能够提供back(), push_back(), pop_front(), priority_queue的基础容器需要提供back(), push_back(), pop_back()的函数。
  5. 你可以你的需要,通过参数传递修改它们的基础容器。比如
    stack < int ,  vector < int > >  st

对于stack和queue还有一个共同点,他们均有重载比较运算符,也就是说你可以对二个stack或者二个queue进行字典许的比较和排序。

STL的stack源码解析

stack的模板可以传递二个参数,第一个是元素类型,第二个是可选的容器类型。类里面有成员变量容器_Sequence c。构造函数有二个,一个函数的参数是左引用的,另外一个函数的参数为右引用的。

template < typename   _Tp ,  typename   _Sequence  =  deque < _Tp > >
     class   stack  
{
protected :
      _Sequence   c ;
private :
     explicit
       stack ( const   _Sequence &  __c )
      :  c ( __c )   {   }
 
       explicit
       stack ( _Sequence &&  __c  =  _Sequence ())
      :  c ( std :: move ( __c ))   {   }
}

stack的特定需求的函数则调用的是c的对应函数,比如下面的代码push函数调用的是c的push_back。

void   push ( const   value_type &  __x )
   {   c . push_back ( __x ) ;  }
   void   pop ()
   {   c . pop_back () ;  }

二个stack的字典序大小也只直接调用容器c的大小比较来实现的。

template < typename   _Tp ,  typename   _Seq >
     inline   bool   operator < ( const   stack < _Tp ,  _Seq >&  __x ,  const   stack < _Tp ,  _Seq >&  __y )
     {   return   __x . c  <  __y . c ;  }

STL的queue源码解析

由于queue的源码原理和实现方式均跟stack相同,这里就省略了。有兴趣的朋友可以自己翻阅源码。

STL的priority_queue源码解析

priority_queue与前面二者不同的是priority_queue不仅仅进行简单的出入队列操作,在这些操作过程,还包括了堆的排序来进行内容的排序。它要求存储元素已经定义了严格的排序关系less,且不提供相等或者大小的比较操作符号。priority_queue属于基于优先级排序的queue,需要注意的是priority_queue默认使用的是最大堆,front()是堆中的最大元素。而且priority_queue在插入和删除元素的时候维护队列的正确性,如果你通过其他方式来操作队列元素或者改变它们的顺序,priority_queue不会重新对队列中的元素重新排序。

priority_queue的模板支持三个参数,第一个参数是存储元素类型,第二个参数是基础容器,默认为vector,第三个参数是比较运算符_Compare,默认为less。为了维护堆的正确性,再构造函数中即对容器进行make_heap的建堆操作。同时你还可以通过传递迭代器的方式来构造 一个priority_queue。

template < typename   _Tp ,  typename   _Sequence  =  vector < _Tp >,
        typename   _Compare   =  less < typename   _Sequence :: value_type > >
     class   priority_queue
{
protected :
       _Sequence   c ;
public :
      explicit
       priority_queue ( const   _Compare &  __x ,
              const   _Sequence &  __s )
      :  c ( __s ) ,  comp ( __x )
       {   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 ) ;
     }
}

一些priority_queue的特殊需求函数跟stack一样也是之间调用容器c的对应函数,比如size()函数和top()函数。

/**  Returns the number of elements in the %queue.  */
       size_type
       size ()   const
       {   return   c . size () ;  }
 
       /**
       *  Returns a read-only (constant) reference to the data at the first
       *  element of the %queue.
       */

       const_reference
       top ()   const
       {
     __glibcxx_requires_nonempty () ;
     return   c . front () ;
       }

priority_queue与queue和stack另外二个不同的地方在于push()和pop()函数。因为它需要再push()和pop()操作的时候进行堆的队列维护,即调用push_heap和pop_heap函数。

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

到此完成STL中特殊容器stack, queue, priority_queue的源码机制解释。如需深入了解,请查阅源代码和相应书籍。

参考书籍

G++源码,版本4.4.4

Nicolai M.Josuttis, The C++ Standard library

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值