STL 笔记(三) 容器适配器 stack、queue、priority_queue

栈 stack

栈 stack 是一种先进后出的(First In Last Out, FILO)的数据结构。在 STL中,stack 底层容器默认使用的是deque, 也可以自己指定用 vector 或 list 容器,然后将其接口适配为栈的接口。部分源代码:

// stack source code (部分)
template <class _Tp,
          class _Sequence __STL_DEPENDENT_DEFAULT_TMPL(deque<_Tp>) >
class stack {
public:
  typedef typename _Sequence::value_type      value_type;
  typedef typename _Sequence::size_type       size_type;
  typedef          _Sequence                  container_type;

  typedef typename _Sequence::reference       reference;
  typedef typename _Sequence::const_reference const_reference;
protected:
  _Sequence c;  // 内部维护的容器, 默认 deque
public:
  stack() : c() {}
  explicit stack(const _Sequence& __s) : c(__s) {}

  bool empty() const { return c.empty(); }           // 是否为空
  size_type size() const { return c.size(); }        // 栈的大小
  reference top() { return c.back(); }               // 访问栈顶元素
  const_reference top() const { return c.back(); }   // 访问栈顶元素(只读)
  void push(const value_type& __x) { c.push_back(__x); }  // 入栈
  void pop() { c.pop_back(); }                            // 出栈
};

队列 queue

队列 queue 是一种先进先出(First In First Out, FIFO)的数据结构。在 STL 中,queue 底层容器默认使用 deque, 然后将其接口适配为队列的接口。部分源代码:

// queue source code (部分)
template <class _Tp,
          class _Sequence __STL_DEPENDENT_DEFAULT_TMPL(deque<_Tp>) >
class queue {
public:
  typedef typename _Sequence::value_type      value_type;
  typedef typename _Sequence::size_type       size_type;
  typedef          _Sequence                  container_type;

  typedef typename _Sequence::reference       reference;
  typedef typename _Sequence::const_reference const_reference;
protected:
  _Sequence c;   // 内部维护的容器, 默认 deque
public:
  queue() : c() {}
  explicit queue(const _Sequence& __c) : c(__c) {}

  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(); }                            // 入队
};

优先级队列 priority_queue

优先级队列 priority_queue 是一种允许用户以任意顺序将元素放入容器,但是取出元素时一定是从最高优先级的元素开始取出。默认值大的优先级高,priority_queue 默认用 vector 容器维护一个最大堆。

简单介绍一下堆,堆一般是一种隐式表述(implicit representation),简单的说堆是由另外一种容器(这里就是 vector )实现。二叉堆 binary-heap 是或近似是完全二叉树,一般用数组来存储,因为其按照层序遍历正好和数组一一对应。堆分为两种:

  • 当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆
  • 当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆

由于堆中的操作都基于父子节点的搜索。如果用数组的话,那么不需要额外的存储空间就可以轻松实现:

  • 左子节点标号 = 父节点标号*2+1
  • 右子节点标号 = 父节点标号*2+2
  • 父节点标号   =(子节点标号-1)/2

另外堆要求数组长度动态,所以用vector实现。部分源代码:

// priority_queue source code (部分)
template <class _Tp,
          class _Sequence __STL_DEPENDENT_DEFAULT_TMPL(vector<_Tp>),
          class _Compare
          __STL_DEPENDENT_DEFAULT_TMPL(less<typename _Sequence::value_type>) >
class priority_queue {
public:
  typedef typename _Sequence::value_type      value_type;
  typedef typename _Sequence::size_type       size_type;
  typedef          _Sequence                  container_type;

  typedef typename _Sequence::reference       reference;
  typedef typename _Sequence::const_reference const_reference;
protected:
  _Sequence c;      // 内部维护容器, 默认 vector
  _Compare comp;    // 优先级决策判别
public:
  priority_queue() : c() {}
  explicit priority_queue(const _Compare& __x) :  c(), comp(__x) {}   //用户可指定自己的优先级决策函数
  priority_queue(const _Compare& __x, const _Sequence& __s)
    : c(__s), comp(__x)
    { make_heap(c.begin(), c.end(), comp); }

  bool empty() const { return c.empty(); }           // 是否为空
  size_type size() const { return c.size(); }        // 队列大小
  const_reference top() const { return c.front(); }  // 访问队首元素(只读,堆顶的元素)
  // 入队
  void push(const value_type& __x) {
    __STL_TRY {
      c.push_back(__x);                    // 先放入 vector c 的尾端
      push_heap(c.begin(), c.end(), comp); // push_heap 泛型算法,元素先插尾端,然后上溯,复杂度为 O(logn)
    }
    __STL_UNWIND(c.clear());
  }
  // 出队
  void pop() {
    __STL_TRY {
      pop_heap(c.begin(), c.end(), comp);
      // (1) 保存 vector 尾部的值到临时变量, ;
      // (2) 将堆顶的值放在 vector 的尾部,堆顶变成空洞节点(空洞对于最大堆可理解为无穷小);
      // (3) 将堆顶的这个空洞下溯,直到移到最底层,成为叶节点;
      // (4) 将原尾部的值放入到已移到底层的空洞中;
      // (5) 对放入空洞的原尾部值在进行上溯,以维持最大堆特点;
      c.pop_back();        // 重排后,删除 vcetor 中的最后一个元素
    }
    __STL_UNWIND(c.clear());
  }
};
时间: 2024-08-07 08:25:08

STL 笔记(三) 容器适配器 stack、queue、priority_queue的相关文章

STL容器适配器 stack, queue

stack是一种后进先出(last in first out)的数据结构.它只有一个出口,如图所示.stack允许新增元素,删除元素,取得最顶端元素.但除了最顶端外,没有其他任何地方可以存储stack的其他元素,换言之,stack不允许有遍历行为. 将元素推入stack的操作称为push, 将元素推出stack的操作称为pop. 为什么将stack称为适配器呢?我们先来看看适配器是怎么定义的.具有这种“修改某物接口,形成另一种风貌”之性质者,称为adapter(适配器).换言之,由于stack的

STL之容器适配器stack的实现框架

说明:本文仅供学习交流,转载请标明出处,欢迎转载! 一提到适配器(adapter).我们就想到了早期用电话线上网所用的调制解调器,俗称"猫"."猫"的作用是实现数模转化和模数转化,在client,它能够将电话的模拟信息转化为我们计算机能够接收的数字信息,所以猫相当于一个转换器.再举个更加好理解的样例来说明"适配器"的含义.相信在我们每一个人的家里都有插排,如果就这么一种情况.如今我们家里的墙壁上仅仅有一个三角的插口,而我们的电视却是两个口,怎么办

UVA11995I Can Guess the Data Structure!(stack + queue + priority_queue)

题目:UVA11995I Can Guess the Data Structure!(stack + queue + priority_queue) 题目大意:给你两种指令,1代表让1后面的数字进入这个数据结构,2代表无差错的从数据结构中取出这个数字,问这个数据结构是stack还是queue还是priority_queue,还是不确定,还是以上均不可能. 解题思路:用STL中的这些数据结构来模拟一下,模拟成功就是这种数据结构,注意pop的时候要判断是否empty. 代码: #include <c

stack queue priority_queue

可以直接使用的数据结构 stack queue priority_queue 头文件 <stack> <queue> <queue> 声明 stack<int>s1 queue<int>q; #include<functional> #include<vector> priority_queue<int,vector<Int>,less<Int>> pq; 从小到大 容量 s1.size

STL标准库-容器适配器

摘要: 技术在于交流.沟通,本文为博主原创文章转载请注明出处并保持作品的完整性 上一节介绍了仿函数适配器,这节主要介绍容器适配器和迭代器适配器的概念,其实容器适配器和迭代器其适配器就是封装了一些其他class的方法,非常好理解. 如果你想让一个calss拥有另一个class的功能,你都可以这样做:1.继承 2.包含 迭代器适配器 运用继承方式,实现适配功能,其实现与仿函数适配器相似. 容器适配器中主要运用的就是包含,即一个类含的一个成员变量是另一个类,本节简单介绍两个容器适配器 容器适配器 qu

STL stack queue priority_queue

栈: empty() pop() push() size() top() 队列: back() empty() front() pop() push() size() 优先队列: empty() pop() push() size() top() priority_queue<int>  pq;   默认升序 priority_queue<int, vector<int>, greater<int> >  pq; 降序 priority_queue<i

uva 11995 I Can Guess the Data Structure stack,queue,priority_queue

题意:给你n个操做,判断是那种数据结构. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<stack> 5 #include<queue> 6 using namespace std; 7 int n; 8 int v[1010],u[1010]; 9 10 int ck_q() 11 { 12 //cout<<"!!"&

容器适配器————stack

只能访问 stack 顶部的元素:只有在移除 stack 顶部的元素后,才能访问下方的元素. 堆栈操作 top():返回一个栈顶元素的引用,类型为 T&.如果栈为空,返回值未定义. push(const T& obj):可以将对象副本压入栈顶.这是通过调用底层容器的 push_back() 函数完成的. push(T&& obj):以移动对象的方式将对象压入栈顶.这是通过调用底层容器的有右值引用参数的 push_back() 函数完成的. pop():弹出栈顶元素. siz

C++ Primer 学习笔记_55_STL剖析(十):容器适配器(stack、 queue 、priority_queue)源码浅析与使用示例

七种基本容器:vector.deque.list.set.multiset.map.multimap 一.容器适配器 stack queue priority_queue stack.queue.priority_queue 都不支持任一种迭代器,它们都是容器适配器类型,stack是用vector/deque/list对象创建了一个先进后出容器:queue是用deque或list对象创建了一个先进先出容器:priority_queue是用vector/deque创建了一个排序队列,内部用二叉堆实