STL源码分析之priority_queue优先级队列

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Function_Dou/article/details/84844960

前言

上一节分析heap其实就是为priority_queue做准备. priority_queue是一个优先级队列, 是带权值的. 支持插入和删除操作, 其只能从尾部插入,头部删除, 并且其顺序也并非是根据加入的顺序排列的. priority_queue因为也是队列的一种体现, 所以也就跟队列一样不能直接的遍历数组, 也就没有迭代器. 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:
	// 符合traits编程规范
  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;	// 定义vector容器的对象
  Compare comp;	// 定义比较函数(伪函数)
  ...
};

构造函数

class  priority_queue {
	...
public:
  priority_queue() : c() {}	// 默认构造函数
  explicit priority_queue(const Compare& x) :  c(), comp(x) {}	// 设置伪函数

#ifdef __STL_MEMBER_TEMPLATES
    // 接受以迭代器类型的参数
    // 接受两个迭代器以及函数. 传入的迭代器范围内表示的元素以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) 
    : c(first, last) { make_heap(c.begin(), c.end(), comp); }
#else /* __STL_MEMBER_TEMPLATES */
     // 接受两个迭代器以及函数. 传入的迭代器范围内表示的元素以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) 
    : c(first, last) { make_heap(c.begin(), c.end(), comp); }
#endif /* __STL_MEMBER_TEMPLATES */
	...
};

属性获取

priority_queue只有简单的3个属性获取的函数, 其本身的操作也很简单, 只是实现依赖了vectorheap就变得比较复杂.

class  priority_queue {
	...
public:
  bool empty() const { return c.empty(); }
  size_type size() const { return c.size(); }
  const_reference top() const { return c.front(); }
    ...
};

push和pop实现

push和pop具体都是采用的heap算法.

class  priority_queue {
	...
public:
  void push(const value_type& x) {
    __STL_TRY {
      c.push_back(x); 
        // 间接使用heap算法
      push_heap(c.begin(), c.end(), comp);
    }
    __STL_UNWIND(c.clear());
  }
  void pop() {
    __STL_TRY {
     	// 间接使用heap算法
      pop_heap(c.begin(), c.end(), comp);
      c.pop_back();
    }
    __STL_UNWIND(c.clear());
  }
};

实际操作

int main()
{
	int a[4] = { 1, 2, 3, 4 };
	priority_queue<int> pq(a, a+4);
	while(!pq.empty())
	{
		cout << pq.top() << " ";	// 4, 3, 2, 1
		pq.pop();
	}

	exit(0);
}

总结

priority_queue本身实现是很复杂的, 但是当我们已经了解过vector, heap之后再来看, 他其实很简单了, 就是将vector作为容器, heap作为算法来操作的配置器, 这也体现了STL的灵活性是很高的, 通过各个容器与算法的结合就能做出另一种功能的结构.

猜你喜欢

转载自blog.csdn.net/Function_Dou/article/details/84844960