C++容器,迭代器,容器的适配器
容器
顺序容器
主要靠下标和迭代器进行操作。顺序性的主要靠下标,链式的靠迭代器访问。
包含了顺序型的容器和链式的容器。
连续型的包括:
vector
:向量,可以快速扩展和删除元素,在队尾的操作有优势!deque
:双端队列,可以快速的从队首和队尾添加或者删除元素,适合双向的操作。array
:数组,大小必须是固定的。string
:字符串
链式的包括:
list
:双向链表forward_list
:单向链表。没有size
操作。
关联容器
简介
主要靠关键字进行访问。关联容器主要是分为两类:set
类型的和map
类型的。同时也可以按照有序和无序分类,也可以按照顺序保存和无序保存分类。
总共有8中类型额关联容器:
map
:关键字-值,关键字唯一set
:关键字,关键字唯一multimap
:关键字-值,关键字可以重复multiset
:关键字:关键字可以重复unordered_map
:哈希函数组织的map
,关键字唯一unordered_set
:哈希函数组织的set
,关键字唯一unordered_multimap
:哈希函数组织的multimap
,关键字不唯一unordered_multiset
:哈希函数组织的multiset
,关键字不唯一
上述以unordered
开头的都是无序的关联容器。关联容器都是支持模板类型操作的。
关联容器不支持顺序容器的那种与位置有关的操作,比如push_back
、push_front
等,这些操作无意义。关联容器的迭代是双向的。
有序关联容器的关键字必须定义比较函数,否则无法放入容器,因为容器需要靠<
比较函数才能进行数据结构的构建。使用有序容器存储自定义的数据类型时,除了给出数据类型的模板之外,还要给出自定义的操作类型。不过我们一般都是重载运算符<
进行操作。
#include <iostream>
#include <set>
using namespace std;class Data1{public:Data1(int _a,int _b=0,int _c=0):a(_a),b(_b),c(_c){}bool operator<(const Data1 &d){return a<d.a;}int a,b,c;
};int main(){set<Data1>s1;return 0;
}
pair
数据类型,存在于utility
头文件。该数据类型用于map
大类的操作,具体有一下几个操作:
pair<T1, T2> p;
声明一个pair
pair<T1, T2> p(v1, v2);
声明并初始化pair<T1, T2>p{v1, v2} ;
声明并初始化auto p=make_pair(v1,v2);
初始化,编译器自动推断所有类型。p.first
:返回键值p.second
:返回对应的数据p1 < p2
:比较的是键值,对于其他的运算符同理。
主要操作
几个特性:
key_type
:容器的关键字类型mapped_type
:每个关键字关联的类型,只适用于map
类型value_type
:数据类型- 对于
set
类型,这与key_type
相同 - 对于
map
类型,为pair<const key_value, mapped_type>
- 对于
上述说的类型是大类。
迭代操作
一般使用自动推导得到迭代器,迭代器是value_type
类型的指针。
对于set
来说,就是元素模板的类型;对于map
来说,是pair<const key_value, mapped_type>
类型。
注意,set
的迭代器是const
类型的,只能读不能修改,这很好理解,因为一旦修改键值,所有的排列顺序都要进行改变;而map
的不能修改键值,但是可以修改键值对应的数据:
#include <iostream>
#include <map>
using namespace std;int main(){map<int,string>m{{1,"a"},{2,"b"}};for(auto it=m.begin();it!=m.end();it++){it->second="new"; // 在这里修改对应的数据}cout<<m[1]<<endl; // 输出newreturn 0;
}
对于迭代操作,只要是有序容器,都是按照字典序输出的。
一般来说,关联容器的迭代器都是只读类型的,我们平时用的sort
等的算法都不适用这种容器,但是可以使用find
的成员给键值定位。也可以使用copy
进行复制操作。
插入操作
单个键值的插入:
使用内置的insert
成员进行操作。几个常用的操作:
c.insert(v)
,插入对应的valut_type
类型的数据c.emplace(args)
,对于单键值的关联容器,只有元素不存在的时候进行插入,多键值的直接插入;返回一个pair
类型的数据,第一个是指向含有关键字的元素,第二个是bool
,表示是否插入成功。c.insert(b,e)
b和e是迭代器,表示插入一个区间的value_type
类型数据c.insert(il)
表示使用花括号的类型
上述的返回值都是一个pair
,作用同上。
多个键值的插入:
不返回任何数据,因为总是可以进行数据插入。
删除操作
使用erase
进行删除操作:
c.erase(k)
:删除关键字为k
的元素,返回删除的个数,不存在返回0c.erase(p)
:删除迭代器指向的元素,必须是内部的,不能是end()
c.erase(b,e)
:删除区间内的元素
map的下标操作
下标操作只适用于map
和unordered_map
,不能用于多键值的;同时,元素必须是非const
类型的。set
没有下标操作。两种数据类型:
c[k]
:返回关键字是k
的元素,如果k
不存在,进添加这个关键字,并初始化c.at(k)
:返回关键为k
的元素,不存在抛出out_of_range
异常
上述返回的都是mapped_type
类型的数据。
访问操作
c.find(k)
:返回第一个迭代器,指向关键字是k
的,不存在返回end()
c.count(k)
:返回关键字为k
的个数c.lower_bound(k)
:返回第一个迭代器,指向第一个关键字不小于k
元素,不适于无序容器!c.upper_bound(k)
:返回第一个迭代器,指向第一个关键字大于k
的元素,不适于无序容器!c.equal_range(k)
:返回一个pair
,表示范围。如果不存在,成员均为end()
无序容器
无序容器使用hash
函数和==
进行运算。主要处理元素没有明显有序关系的情况,理论上有更好的性能,但是实际上需要多次进行工程验证效率。
无序容器的插入删除和有序容器基本一致,只是没有和序列有关的操作。无序容器使用了一个链式的桶状结构,性能取决于哈希函数的质量和桶的数量与大小。如果是自定义的数据类型,我们需要自己来说明哈希函数,否则不能直接使用。
#include <iostream>
#include <unordered_set> // 注意头文件
#include <string>
#include <functional>
using namespace std;class Data{public:Data(int a,string s):n(a),str(s){}int n;string str;
};size_t hasher(const Data &d){return hash<string>()(d.str);
}bool cmp(const Data& d1, const Data &d2){return d1.str==d2.str;
}int main(){using SD_multiset=unordered_multiset<Data,decltype(hasher)*, decltype(cmp)*>;// 桶的大小,哈希函数,比较函数SD_multiset data_set(10,hasher,cmp);Data d(1,"hello");data_set.insert(d);return 0;
}
迭代器
迭代器是一个泛型的指针类型,只要是可迭代的容器,都可以使用迭代器。适配器不可以使用,比如stack
、queue
和priority_queue
等的数据类型。
begin()
是首元素end()
是尾后元素- 若容器是空的,则
begin()==end()
迭代器的标准运算成员:
*iter
取内容iter->item
取出内部的成员++iter
指向下一个元素--iter
指向上一个iter1==iter2
判断是否指向同一个元素iter1!=iter2
不指向同一个元素的判定
使用了迭代器的循环体,不要向迭代器所属的容器添加元素!!!
非标准迭代器成员的运算符号根据具体的容器确定。
容器的适配器
容器的适配器是一个机制,使得某种事物看起来像另一种事物。给出基本类型和操作:
size_type
:保证当前类型的最大对象的大小value_type
:元素的类型container_type
:实现适配器底层容器的类型A a
:创建一个A类型的空适配器aA a(c)
:创建一个名为a的适配器,带有容器c
的一个拷贝!!!a.empty()
:判断是否是空,空返回true
,否则是false
a.size()
:返回元素的个数swap(a,b)
:交换a,b的内容,要求比素食同类型的元素,底层容器类型也必须相同a.swap(b)
:同上
栈默认使用deque
作为底层,队列默认使用deque
,priority_queue
默认使用vector
作为底层。也可以自定义底层容器。需要注意的是:适配器不能进行迭代!!
C++容器,迭代器,容器的适配器相关推荐
- C++STL总结笔记(一)—— 容器和容器适配器
文章目录 前言 一.概念 1.1 顺序容器 1.2 容器适配器 1.3 关联容器 二.程序示例 1. vector和Set自定义数据类型的访问 2.vector容器嵌套 3.list容器排序 4.pa ...
- STL 容器简介:C++ 容器:顺序性容器、关联式容器和容器适配器
STL标准容器类简介 标准容器类 说明 顺序性容器 vector 从后面快速的插入与删除,直接访问任何元素 deque 从前面或后面快速的插入与删除,直接访问任何元素 list 双链表,从任何地方快速 ...
- QT学习笔记(九):遍历容器-迭代器(iterators)
QT学习笔记(九):遍历容器-迭代器(iterators) 遍历容器 : 1.Jave风格: 2.STL风格: 3.foreach 关键字: 遍历容器 : 遍历一个容器可以使用迭代器(iterator ...
- C++11中容器迭代器操作总结
C++11中标准容器迭代器操作总结 我发现有必要对各类容器迭代器的操作做一个小小的总结,本文中的内容大多来自于<C++ Primer>(第5版)中相关章节的内容. 1.下面列 ...
- C++中的容器(STL容器)container
1.容器 容器(container)用于存放数据的类模板.可变长数组.链表.平衡二叉树等数据结构在STL中都被实现为容器.使用容器时,即将容器类模板实例化为容器类时,会指明容器中存放的元素是什么类型的 ...
- 关联容器----关联容器概述,关联容器操作,无序容器
关联容器和顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的.与之相对,顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的. 关联容器支持高效的关键字查找和访问.两个主要的关联容器 ...
- 【STL四】序列容器——vector容器
[STL容器]序列容器--vector容器 一.简介 二.头文件 三.模板类 四.成员函数 1.迭代器 2.元素访问 3.容量 4.修改操作 五.demo 1.容量reserve.capacity.s ...
- Docker 容器技术 — 容器存储
目录 文章目录 目录 容器存储 数据卷管理 挂载时创建卷 创建卷后挂载 数据容器管理 容器存储 数据卷管理 核心选项: -v 宿主机目录:指定挂载到容器内的目录. 映射多个宿主机目录,只需要多写几个 ...
- Docker 容器技术 — 容器网络
目录 文章目录 目录 CNM CNM 驱动接口 网络驱动 IPAM 驱动 Docker 原生网络驱动 Bridge 模式(默认) 用户自定义 Bridge 网络 Host 模式 外部访问容器(容器的端 ...
- Web服务器 Web容器 Servlet容器
WEB服务器也称为WWW(WORLD WIDE WEB)服务器,主要功能是提供网上信息浏览服务. WWW 是 Internet 的多媒体信息查询工具,是 Internet 上近年才发展起来的服务,也是 ...
最新文章
- 【青少年编程】【四级】从小到大排序
- PacBio But Not Illumina Technology Can Achieve Fast, Accurate and Complete Closure of the High GC, C
- Enterprise Manager Cloud Control 安装
- iOS视图控制对象生命周期-init、viewDidLoad、viewWillAppear、viewDidAppear、viewWillDisappear、view...
- matlab的离散求导,高手留步:MATLAB五阶拟合函数,求导后离散化,输出结果是星号...
- 帆软报表(finereport)单元格函数,OP参数
- BeetleX自定义http/websocket压测用例视频
- 显卡天梯图:2014最新显卡性能天梯图
- Ambari离线部署Hadoop集群踩到的坑
- x-requested-with 请求头 区分ajax请求还是普通请求
- phpadmin 安装
- utf-8、unicode区别与联系
- html调整div上下顺序,用了float后div块之间的上下顺序不对了_html/css_WEB-ITnose
- 前端js实现打印excel表格
- 20145202马超《java》实验5
- Wl,-rpath的格式问题,Wl,--rpath
- SWMM模型代码LID(Low Impact Development)模块分析
- python Word批量转PDF
- ChinaVis 2017
- maven报错问题汇总
热门文章
- java entrypoint_java – 有时只调用AuthenticationEntryPoint
- 终端操作MySQL数据库
- PyTorch报错“/.../Loss.cu: ... [59,0,0] Assertion input_val >= zero input_val <= one failed.”
- r语言去除字符串两端多余空格
- 用于Ubuntu 16.04和18.04的TensorFlow,Keras,Caffe,Caffe,CUDA,cuDNN和NVIDIA驱动程序的单行安装
- JS小技巧 ----- 关于 ... 运算符的使用场景
- GTK+图形化应用程序开发学习笔记(一)—概述
- this.grid is undefined
- JAVA——孪生素数
- Selenium WebDriver Api 知识梳理