SGISTL源码探究-优先级队列

前言

在上一小节中,我们分析了heap算法,其实是为了priority_queue优先级队列做准备,它也不是容器,而是配接器,因为它是通过vector来实现的,然后封装了一些vector提供的接口供自己使用而形成的。
优先级队列,即一种特殊的队列,但是它内部的元素没有按照传统队列的先进先出这种顺序排序,而是按照元素的权值进行排列,所以执行出队操作时,出队的是权值最大的元素。

priority_queue

在SGISTL的实现中,priority_queue队列底部实现的容器就是vector,然后再配合heap提供的一些算法就可以完成优先级队列的所有功能了。
它的实现源码如下:

定义部分
#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) {}

#ifdef __STL_MEMBER_TEMPLATES
  //以迭代器范围构造时,调用make_heap函数使这些元素形成堆结构
  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 */
提供的接口
  bool empty() const { return c.empty(); }
  size_type size() const { return c.size(); }
  //返回堆顶的值,即权值最高的元素
  const_reference top() const { return c.front(); }
  /* 将元素压入优先级队列
   * 先将元素压入vector尾部
   * 然后调用push_heap进行调整
   */
  void push(const value_type& x) {
    __STL_TRY {
      c.push_back(x);
      push_heap(c.begin(), c.end(), comp);
    }
    __STL_UNWIND(c.clear());
  }
  /* 调用pop_heap将权值最大的元素存在vector尾部
   * 接着调用vector提供的pop_back弹出尾部元素
   */
  void pop() {
    __STL_TRY {
      pop_heap(c.begin(), c.end(), comp);
      c.pop_back();
    }
    __STL_UNWIND(c.clear());
  }
};
例子
#include <iostream>
#include <queue>
using namespace std;
int main()
{
    vector<int> vec{0, 1, 2, 3, 4, 5, 6};
    priority_queue<int> pri_que(vec.begin(), vec.end());


    while(!pri_que.empty())
    {
        cout << pri_que.top() << endl;
        pri_que.pop();
    }

    pri_que.push(10);
    cout << pri_que.top() << endl;

    return 0;
}

很简单的一个例子,这里为了方便理解,就只使用了最普通的int作为权值,你可以尝试声明一个对象,然后定义自己的compare类作为大小比较标准,然后在创建priority_queue的时候指定比较标准。

小结

在本小节中,我们分析了priority_queue的实现,其实它的实现很简单,在我们并没有深入源码的时候可能觉得它很复杂,但是并不是。
priority_queue主要借用了vector作为底部容器,以及使用了heap有关的算法,只是改变了相应的接口,就形成了另外一种数据结构,不得不感叹stl的精妙。
关于序列式容器,我们就告一段落,接下来我们将进入到关联式容器。但是由于setmap这类关联式容器都借助了红黑树实现,所以我们要先对红黑树做个了解。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值