26. STL容器适配器

容器适配器就是将不适用的序列式容器(包括 vector、deque 和 list)变得适用。通过封装某个序列式容器,并重新组合该容器中包含的成员函数,使其满足某些特定场景的需要。容器适配器本质上还是容器,只不过此容器模板类的实现,利用了大量其它基础容器模板类中已经写好的成员函数。当然,如果必要的话,容器适配器中也可以自创新的成员函数。

STL 提供了 3 种容器适配器,分别为 stack 栈适配器、queue 队列适配器以及 priority_queue 优先权队列适配器:

容器适配器 基础容器筛选条件 默认使用的基础容器
stack 基础容器需包含以下成员函数:empty(); size(); back(); push_back(); pop_back(); 满足条件的基础容器有 vector、deque、list。 deque
queue 基础容器需包含以下成员函数:empty(); size(); front(); back(); push_back(); pop_front(); 满足条件的基础容器有 deque、list。 deque
priority_queue 基础容器需包含以下成员函数:empty(); size(); front(); push_back(); pop_back(); 满足条件的基础容器有vector、deque。 vector

27. stack栈适配器

1)创建

#include<stack> //stack<T,Container=deque<T>>(其中 T 为存储元素的类型,Container 表示底层容器的类型)的形式位于<stack>头文件中
using namespace std;stack<int> val1;deque<int> deq{1,2,3};
stack<int> val2(deq); //val3中栈顶元素还是3list<int> li{1,2,3};
stack<int, list<int>> val3(li);//指定使用list容器stack<int> val4(val2); //使用 stack适配器给另一个stack进行初始化

2)成员函数

成员函数 功能
empty() 当 stack 栈中没有元素时,该成员函数返回 true;反之,返回 false。
size() 返回 stack 栈中存储元素的个数。
top() 返回一个栈顶元素的引用,类型为 T&。如果栈为空,程序会报错。
push(const T& val) ==先复制 val,再将 val 副本压入栈顶。==这是通过调用底层容器的 push_back() 函数完成的。
push(T&& obj) ==以移动元素的方式将其压入栈顶。==这是通过调用底层容器的有右值引用参数的 push_back() 函数完成的。
pop() 弹出栈顶元素。
emplace(arg…) arg… 可以是一个参数,也可以是多个参数,但它们都只用于构造一个对象,并在栈顶直接生成该对象,作为新的栈顶元素。
swap(stack & other_stack) ==将两个 stack 适配器中的元素进行互换,==需要注意的是,进行互换的 2 个 stack 适配器中存储的元素类型以及底层采用的基础容器类型,都必须相同。

28. queue容器适配器

1)创建

#include<queue>//以模板类 queue<T,Container=deque<T>>(其中 T 为存储元素的类型,Container 表示底层容器的类型)的形式位于<queue>头文件中
using namespace std;queue<int> val1;queue<int, list<int>> val2;//手动指定 queue 容器适配器底层采用的基础容器类型dueue<int> val3{1,2,3};
queue<int> val4(val3); //用基础容器来初始化 queue 容器适配器,只要该容器类型和 queue 底层使用的基础容器类型相同即可queue<int> val5(val4); //直接通过 queue 容器适配器来初始化另一个 queue 容器适配器

2)成员函数

成员函数 功能
empty() 如果 queue 中没有元素的话,返回 true。
size() 返回 queue 中元素的个数。
front() ==返回 queue 中第一个元素的引用。==如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。
back() ==返回 queue 中最后一个元素的引用。==如果 queue 是常量,就返回一个常引用;如果 queue 为空,返回值是未定义的。
push(const T& obj) ==在 queue 的尾部添加一个元素的副本。==这是通过调用底层容器的成员函数 push_back() 来完成的。
emplace() 在 queue 的尾部直接添加一个元素。
push(T&& obj) ==以移动的方式在 queue 的尾部添加元素。==这是通过调用底层容器的具有右值引用参数的成员函数 push_back() 来完成的。
pop() 删除 queue 中的第一个元素。
swap(queue &other_queue) 将两个 queue 容器适配器中的元素进行互换,需要注意的是,进行互换的 2 个 queue 容器适配器中存储的元素类型以及底层采用的基础容器类型,都必须相同。

和 stack 一样,queue 也没有迭代器,因此访问元素的唯一方式是遍历容器,通过不断移除访问过的元素,去访问下一个元素。

#include<iostream>
#include<queue>
using namespace std;int main(){deque<int> my_deque{1,2,3};queue<int> my_queue(my_deque);cout<<my_queue.size()<<endl;while(!my_queue.empty()){cout<<my_queue.front()<<endl;my_queue.pop();}return 0;
}

29. priority_queue容器适配器

priority_queue 容器适配器模拟的也是队列这种存储结构,但是,priority_queue 容器适配器中元素的存和取,遵循的并不是 “First in,First out”(先入先出)原则,先进队列的元素并不一定先出队列,而是优先级最大的元素最先出队列。

priority_queue 容器适配器为了保证每次从队头移除的都是当前优先级最高的元素,每当有新元素进入,它都会根据既定的排序规则找到优先级最高的元素,并将其移动到队列的队头;同样,当 priority_queue 从队头移除出一个元素之后,它也会再找到当前优先级最高的元素,并将其移动到队头。

//priority_queue定义
template <typename T, //指定存储元素的具体类型typename Container=std::vector<T>, //指定 priority_queue 底层使用的基础容器,默认使用 vector 容器typename Compare=std::less<T> > //指定容器中评定元素优先级所遵循的排序规则,默认使用std::less<T>按照元素值从大到小进行排序,还可以使用std::greater<T>按照元素值从小到大排序
class priority_queue{//......
}

1)创建

#include<queue>
using namespace std;
//创建空的适配器
priority_queue<int> p_queue;
//使用普通数组或其他容器中指定范围内的数据
int values1[]{4,2,3,1};
priority_queue<int> p_queue1(values1, values1+4); //{4,3,2,1}
std::array<int,4> values2{4,2,3,1};
priority_queue<int> p_queue2(values2.begin(), values2.end());
//手动指定使用的底层容器及排序规则
priority_queue<int, deque<int>, greater<int>> p_queue3(values1, values1+4);

2)成员函数

成员函数 功能
empty() 如果 priority_queue 为空的话,返回 true;反之,返回 false。
size() 返回 priority_queue 中存储元素的个数。
top() 返回 priority_queue 中第一个元素的引用形式。
push(const T& obj) 根据既定的排序规则,将元素 obj 的副本存储到 priority_queue 中适当的位置。
push(T&& obj) 根据既定的排序规则,将元素 obj 移动存储到 priority_queue 中适当的位置。
emplace(Args&&… args) Args&&… args 表示构造一个存储类型的元素所需要的数据(对于类对象来说,可能需要多个数据构造出一个对象)。此函数的功能是根据既定的排序规则,在容器适配器适当的位置直接生成该新元素。
pop() 移除 priority_queue 容器适配器中第一个元素。
swap(priority_queue& other) 将两个 priority_queue 容器适配器中的元素进行互换,需要注意的是,进行互换的 2 个 priority_queue 容器适配器中存储的元素类型以及底层采用的基础容器类型,都必须相同。

和 queue 一样,priority_queue 也没有迭代器,因此访问元素的唯一方式是遍历容器,通过不断移除访问过的元素,去访问下一个元素。

30. priority_queue适配器实现自定义排序

当 <function> 头文件提供的排序方式(std::less<T> 和 std::greater<T>)不再适用时,需要自定义一个满足需求的排序规则

#include<iostream>
#include<queue>
using namespace std;
//函数对象类
template <typename T>
class cmp{public://重载 () 运算符bool operator()(T a, T b){return a > b;}
};int main(){int a[] = { 4,2,3,5,6 };priority_queue<int,vector<int>,cmp<int> > pq(a,a+5);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}return 0;
}
#include<queue>
#include<iostream>
using namespace std;
class node {public:node(int x = 0, int y = 0) :x(x), y(y) {}int x, y;//以成员函数的方式重载//bool operator < (const node &b) const{//    if ((*this).x > b.x) return 1;//   else if ((*this).x == b.x)//       if ((*this).y >= b.y) return 1;//   return 0;//}//以友元函数的方式重载//friend bool operator <(const node& a, const node& b);
};//通过重载 < 运算符,使得 std::less<T> 变得适用
//新的排序规则为:先按照 x 值排序,如果 x 相等,则按 y 的值排序
bool operator < (const node &a, const node &b) {if (a.x > b.x) return 1;else if (a.x == b.x)if (a.y >= b.y) return 1;return 0;
}int main() {//创建一个 priority_queue 容器适配器,其使用默认的 vector 基础容器以及 less 排序规则。priority_queue<node> pq;pq.push(node(1, 2));pq.push(node(2, 2));pq.push(node(3, 4));pq.push(node(3, 3));pq.push(node(2, 3));cout << "x y" << endl;while (!pq.empty()) {cout << pq.top().x << " " << pq.top().y << endl;pq.pop();}return 0;
}

总的来说,以函数对象的方式自定义 priority_queue 的排序规则,适用于任何情况;而以重载 > 或者 < 运算符间接实现 priority_queue 自定义排序的方式,仅适用于 priority_queue 中存储的是结构体变量或者类对象(包括 string 类对象)。

31. priority_queue容器的底层实现

priority_queue 优先级队列之所以总能保证优先级最高的元素位于队头,最重要的原因是其底层采用堆数据结构存储结构。priority_queue 底层采用 vector 或 deque 容器存储数据,这里又说使用堆结构存储数据,它们之间并不冲突。vector 和 deque 是用来存储元素的容器,而堆是一种数据结构,其本身无法存储数据,只能依附于某个存储介质,辅助其组织数据存储的先后次序。

堆是在完全二叉树的基础上,要求树中所有的父节点和子节点之间,都要满足既定的排序规则:

  • 如果排序规则为从大到小排序,则表示堆的完全二叉树中,每个父节点的值都要不小于子节点的值,这种堆通常称为大顶堆
  • 如果排序规则为从小到大排序,则表示堆的完全二叉树中,每个父节点的值都要不大于子节点的值,这种堆通常称为小顶堆

eg:{10,20,15,30,40,25,35,50,45}元素构成的大/小顶堆

STL 封装好了可以使用堆存储结构的方法,它们都位于 <algorithm> 头文件中:

函数 功能
make_heap(first,last,comp) 选择位于 [first,last) 区域内的数据,并根据 comp 排序规则建立堆,其中 fist 和 last 可以是指针或者迭代器,默认是建立大顶堆。
push_heap(first,last,comp) 当向数组或容器中添加数据之后,此数据可能会破坏堆结构,该函数的功能是重建堆。
pop_heap(first,last,comp) 将位于序列头部的元素(优先级最高)移动序列尾部,并使[first,last-1] 区域内的元素满足堆存储结构。
sort_heap(first,last,comp) 对 [first,last) 区域内的元素进行堆排序,将其变成一个有序序列。
is_heap_until(first,last,comp) 发现[first,last)区域内的最大堆。
is_heap(first,last,comp) 检查 [first,last) 区域内的元素,是否为堆结构。

参考

1.http://c.biancheng.net/stl/

C++ STL库(6)相关推荐

  1. C++11 中STL库中新增内容

    C++ 11一个比较显著的变化是以前boost库中的一些函数被正式标准化合入到STL中了,本文就简单的介绍一下. 引用包装器(Reference Wrapper) 当模板函数参数为泛型类型的时候,无法 ...

  2. STL库容器vector at函数

    STL库容器vector at函数 v.at(n)返回v指定位置n的元素.at函数比[]运算符更加安全, 因为它不会让你去访问到越界的元素,一旦越界将会在运行时中止程序并抛出一个异常std::out_ ...

  3. c++中algorithm头文件、STL库简介及使用说明

    c++中algorithm头文件.STL库简介及使用说明 c++中algorithm头文件是STL的算法部分,里边定义了各种算法,比如sort之类的.加上algorithm就可以使用stl库里的各种算 ...

  4. STL库中string类内存布局的探究

    在STL中有着一个类就是string类,他的内存布局和存储机制究竟是怎么样的呢? 这就是建立好的string 可以看出,图中用黄色框框标注的部分就是主要区域 我们用来给string对象进行初始化的字符 ...

  5. [c++]巧用stl库-啤酒与尿布

    [c++]<-巧用stl库-> 啤酒与尿布 前言 大家好,楼主计算机专业大学狗一枚.<啤酒与尿布>是专业课的一道课后习题,觉得我个人思路比较新颖,在此分享.能力一般,水平有限, ...

  6. 例题5-3安迪的第一个字典 UVa10815--C++STL库映射set的应用

    前言 不定期更新C++的STL库以及算法练习的笔记 分享给大家 也是督促自己不断努力学习算法与程序设计 学习算法之前,要想高效简洁的写好代码,还需要熟练掌握STL库的一些方法和数据结构 参考书籍: & ...

  7. STL库:string

    STL库:string 文章目录 STL库:string 1.STL库对于string类的介绍 2.string常用接口的掌握 2.1 string的构造接口 2.2 string的容量操作接口 2. ...

  8. STL库:vector

    STL库:vector 文章目录 STL库:vector 1.STL库对vector的官方介绍 2.vecotr的常用接口 2.1 vector的构造函数 2.2 vector的迭代器与遍历操作 2. ...

  9. STL库:map和set

    STL库:map和set 文章目录 STL库:map和set 1.STL库中set的官方介绍 2.set的常用接口 3.set的总结 4.STL库中multiset的官方介绍 5.STL库中map的官 ...

  10. 【C++】算法STL库

    26 算法STL库 26.1 算法特点 使用迭代器指定范围,使用函数作为参数处理数据. 26.2 算法的两个主要泛型元素 1.模板提供泛型类型 ​ 2.迭代器提供数据的通用访问表示 26.3 算法分组 ...

最新文章

  1. C++编程练习(5)----“实现简单的循环队列的顺序存储结构“
  2. rt-thread 自动初始化机制分析-关于编译链接及段信息
  3. silverlightLogo动画
  4. 去哪儿-06-home-ajax
  5. Python GUI界面编程初步 03 - Tkinter基础设计案例
  6. document 文挡对象详解(JavaScript脚本语言描述)
  7. springcloud项目的启动顺序_spring boot/cloud 启动方式说明
  8. 腾讯基于预训练模型的文本内容理解实践
  9. API 接口设计中 Token 类型的分类与设计
  10. boost 安装_Win10 + VS2019 编译安装 Boost
  11. 【SQL注入16】SQL漏洞利用之读写文件
  12. FreeImage的学习资料汇总
  13. 增加项目报告功能,支持与TAPD、Jira、禅道双向同步缺陷,MeterSphere开源持续测试平台v1.15.0发布
  14. 推荐几部好看的漫画,漫迷们不容错过的动漫新番哦
  15. C#做一个简单浏览器
  16. JavaWeb进阶之路:MyBatis-配置解析
  17. 北京周边10个樱桃采摘地
  18. 网站首页html静态化,网站首页怎么静态化
  19. SylixOS更新记录
  20. c调用python第三方包_cbillington_Python包维护者_第三方库作者_PyPI项目模块Package - Python中文网...

热门文章

  1. 中望CAD工具栏消失不见的解决方案
  2. Javascript常用函数、方法速查手册
  3. 基于SpringBoot的救援物资管理系统
  4. 数字化转型提出新要求 新华三IT基础架构如何随需而变?
  5. 直升机救援机制的发展
  6. idea2017 破解版使用
  7. win10易升_win10性能模式是什么?怎么开启?
  8. 考华为认证需要准备什么
  9. iOS逆向:破解 APP防止dyld注入 的方法
  10. 两个队列实现一个栈(C++实现)