疯子的算法总结(三) STL Ⅱ迭代器(iterator) + 容器
一、迭代器(Iterator)
背景:指针可以用来遍历存储空间连续的数据结构,但是对于存储空间费连续的,就需要寻找一个行为类似指针的类,来对非数组的数据结构进行遍历。
定义:迭代器是一种检查容器内元素并遍历元素的数据类型。
迭代器提供对一个容器中的对象的访问方法,并且定义了容器中对象的范围。
迭代器(Iterator)是指针(pointer)的泛化,它允许程序员用相同的方式处理不同的数据结构(容器)。
(1)迭代器类似于C语言里面的指针类型,它提供了对对象的间接访问。
(2)指针是C语言中的知识点,迭代器是C++中的知识点。指针较灵活,迭代器功能较丰富。
(3)迭代器提供一个对容器对象或者string对象的访问方法,并定义了容器范围。
迭代器和指针的区别:
容器和string有迭代器类型同时拥有返回迭代器的成员。如:容器有成员begin和end,其中begin成员复制返回指向第一个元素的迭代器,而end成员返回指向容器尾元素的下一个位置的迭代器,也就是说end指示的是第一个不合法地址,所以end返回的是尾后迭代器。
容器迭代器的使用
每种容器类型都定义了自己的迭代器类型,如vector:vector< int>:: iterator iter;//定义一个名为iter的变量,数据类型是由vector< int>定义的iterator 类型。简单说就是容器类定义了自己的iterator类型,用于访问容器内的元素。每个容器定义了一种名为iterator的类型,这种类型支持迭代器的各种行为。
我么们先讲一下各种迭代器的类型,在讲容器所用的迭代器类型,就可以明白怎么操作。
常见迭代器类型如下:
所有迭代器 | 操作 |
---|---|
p++ | 后置自增迭代器 |
++p | 前置自增迭代器 |
输入迭代器 | 操作介绍 |
*p | 复引用迭代器,作为右值 |
p=p1 | 将一个迭代器赋给另一个迭代器(迭代器指向地址值) |
p==p1 | 比较迭代器的相等性(比较地址) |
p!=p1 | 比较迭代器的不等性 |
输出迭代器 | 操作 |
*p | 复引用迭代器,作为左值 |
p=p1 | 将一个迭代器赋给另一个迭代器 |
正向迭代器 | 提供输入输出迭代器的所有功能 |
双向迭代器 | 操作 |
–p | 前置自减迭代器 |
p– | 后置自减迭代器 |
随机迭代器 | |
p+=i | 将迭代器递增i位 |
p-=i | 将迭代器递减i位 |
p+i | 在p位加i位后的迭代器 |
p-i | 在p位减i位后的迭代器 |
p[i] | 返回p位元素偏离i位的元素引用 |
p<p1 | 如果迭代器p的位置在p1前,返回true,否则返回false |
p<=p1 | p的位置在p1的前面或同一位置时返回true,否则返回false |
p>p1 | 如果迭代器p的位置在p1后,返回true,否则返回false |
p>=p1 | p的位置在p1的后面或同一位置时返回true,否则返回false |
只有顺序容器和关联容器支持迭代器遍历,各容器支持的迭代器的类别如下:
容器 | 支持的迭代器类别 | 说明 |
---|---|---|
vector | 随机访问 | 一种随机访问的数组类型,提供了对数组元素进行快速随机访问以及在序列尾部进行快速的插入和删除操作的功能。可以再需要的时候修改其自身的大小 |
deque | 随机访问 | 一种随机访问的数组类型,提供了序列两端快速进行插入和删除操作的功能。可以再需要的时候修改其自身的大小 |
list | 双向 | 一种不支持随机访问的数组类型,插入和删除所花费的时间是固定的,与位置无关。 |
set | 双向 | 一种随机存取的容器,其关键字和数据元素是同一个值。所有元素都必须具有惟一值。 |
multiset | 双向 | 一种随机存取的容器,其关键字和数据元素是同一个值。可以包含重复的元素。 |
map | 双向 | 一种包含成对数值的容器,一个值是实际数据值,另一个是用来寻找数据的关键字。一个特定的关键字只能与一个元素关联。 |
multimap | 双向 | 一种包含成对数值的容器,一个值是实际数据值,另一个是用来寻找数据的关键字。一个关键字可以与多个数据元素关联。 |
stack | 不支持 | 适配器容器类型,用vector,deque或list对象创建了一个先进后出容器 |
queue | 不支持 | 适配器容器类型,用deque或list对象创建了一个先进先出容器 |
priority_queue | 不支持 | 适配器容器类型,用vector或deque对象创建了一个排序队列 |
二、容器
所有容器都支持自定义数据类型,就是结构体。
(一) vector
使用此容器需在程序前加上头文件#include< vector >。
vector可理解为变长数组,基于倍增思想。当以已申请vector长度为m时,若实际长度n=m,则申请长度为2m的数组,将内容转移至新地址上,并释放旧空间;删除元素时,若n<=m/4,则释放一半空间。
vector容器能像数组一样随机访问第i个数a[i],但不支持随机插入.
#include<vector> //头文件
vector<int> a; 定义了一个int类型的vector容器a
vector<int> b[100];定义了一个int类型的vector容器b组
struct rec{···};
vector<rec> c; /定义了一个rec类型的vector容器c
vector<int>::iterator it; //vector的迭代器,与指针类似
具体操作如下:
a.size() //返回实际长度(元素个数),O(1)复杂度a.empty() //容器为空返回1,否则返回0,O(1)复杂度a.clear() //把vector清空a.begin() //返回指向第一个元素的迭代器,*a.begin()与a[0]作用相同a.end() //越界访问,指向vector尾部,指向第n个元素再往后的边界a.front() //返回第一个元素的值,等价于*a.begin和a[0]a.back() //返回最后一个元素的值,等价于*--a.end()和a[size()-1]a.push_back(x) //把元素x插入vector尾部a.pop_back() //删除vector中最后一个元素
迭代器使用与指针类似,可如下遍历整个容器
for ( vector<int>::iterator it=a.begin() ; it!=a.end() ; it++ )
queue
循环队列queue需使用头文件< queue >
queue<int> q; //定义了一个int类型的队列容器q
struct rec{···};queue<rec> q; //定义了一个rec类型的队列容器q
q.push(x); //从队尾使元素x入队,O(1)
q.pop(x); //使队首元素出队,O(1)
int x=q.front(); //询问队首元素的值,O(1)
int y=q.back(); //询问队尾元素的值,O(1)
priority_queue
优先队列priority_queue可理解为一个大根二叉堆,必须定义“小于号”,而int,string本身就能比较。同样需要头文件< queue >。
其定义方式与queue相似。
priority_queue<int> q; 由大到小
priority_queue<pair<int,int>> q; //pair是一个数对,由first和scond两个元素构成,按照第一个排序
priority_queue<int, vector<int>, greater<int> >qi2; //由小到大,小根堆,vector<int>是适配器,不用知道很详细,记住就行
struct rec //举个栗子
{int a,b,c;bool operator<(const rec&w){if(a==w.a) return b==w.b?c<w.c:b<w.b;return a<w.a;}
};
priority_queue<rec> q; 如果不写重载函数,会出错,他不知道怎么排序
q.push(x); //插入 O(log n)
q.pop(); //删除堆顶元素 O(log n)
q.top(); //查询堆顶元素 O(1)
可通过插入元素的相反数取出时再取反,或重载“小于号”的方式实现小根堆,通过懒惰删除法实现随机删除操作。
deque
双端队列,是一个支持在两端高效插入或删除元素的连续线性存储空间,可像数组一样随机访问,使用前加头文件< deque >。
q.begin()/q.end() //头/尾迭代器,与vector类似
q.front()/q.back() //头/尾元素,与queue类似
q.push_back(x)/q.push_front(x) //从队尾/队头入队
q.pop_back(x)/q.pop_front(x) //从队尾/队头出队
q.clear() //清空队列
定义方式
deque<类型> 名称
ps:clear复杂度为O(n),其余为O(1)。
set/multiset
两容器相似,但set为有序集合,元素不能重复,multiset为有序多重集合,可包含若干相等的元素,内部通过红黑树实现,支持的函数基本相同,同样必须定义“小于号”运算符,头文件为< set >。
其迭代器不支持随机访问,支持星号(*)结束引用,仅支持 ++ 、-- 两个与算术有关的操作。迭代器it++,则指向从小到大排序的结果中排在it下一名的元素,两操作时间复杂度均为O(log n)。
q.size() //返回容器内元素个数
q.empty() //判断容器是否为空
q.clear() //清空容器
q.begin()/q.end() //作用与上文几种容器类似
q.insert(x) //将元素x插入集合中,O(log n)
q.find(x) //查找等于x的元素,返回其迭代器,无则返回q.end(),O(log n)
q.lower_bound(x) //查找>=x的元素中最小的一个,返回指向该元素的迭代器
q.upper_bound(x) //查找>x的元素中最小的一个,返回指向该元素的迭代器
q.erase(it) //删除迭代器it指向的元素,O(log n)
q.erase(x) //删除所有等于x的元素,复杂度为O(k+log n),k为被删除的元素个数
q.count(x) //返回等于x的元素个数,O(k+log n),k为元素x的个数
定义方式
set<int> demo 定义一个类型为int的set容器
struct rec
{int a,b,c;bool operator<(const rec&w){if(a==w.a) return b==w.b?c<w.c:b<w.b;return a<w.a;}
};set<rec> ob; 一样所有排序的容器不重载就出错
map/multimap
map/multimap映射容器的元素数据是由一个Key和一个Value成的,key与映照value之间具有一一映照的关系。
map/multimap容器的数据结构也采用红黑树来实现的,map插入元素的键值不允许重复,类似multiset,multimap的key可以重复。比较函数只对元素的key进行比较,元素的各项数据只能通过key检索出来。虽然map与set采用的都是红黑树的结构,但跟set的区别主要是set的一个键值和一个映射数据相等,Key=Value。
map<first,second> a;
//map,会按照first(键值)排序(查找也是);
map/multimap用法
头文件
#include< map >
map成员函数
begin() //返回指向 map 头部的迭代器
clear() // 删除所有元素
count() //返回指定元素出现的次数
empty() // 如果 map 为空则返回 true
end() //返回指向 map 末尾的迭代器
erase() // 删除一个元素
find() // 查找一个元素
insert() //插入元素
key_comp() //返回比较元素 key 的函数
lower_bound() //返回键值>=给定元素的第一个位置
max_size() //返回可以容纳的最大元素个数
rbegin() //返回一个指向 map 尾部的逆向迭代器
rend() //返回一个指向 map 头部的逆向迭代器
size() //返回 map 中元素的个数
swap() //交换两个 map
创建map对象
#include<iostream>
#include<map>
using namespace std;
map<int,char>mp;//定义map容器
创建结构体map对象
struct student{
int birth;
string name;
};
int id;
typedef map<int,student> Student;// 这里相当于给map<int,student> 起了个别名Student,后续代码均可以用student代替map<int,student> 使用。
插入结构体对象
接上文代码
Stduent a;
cin>>id>>student.birth>>student.name;
a.insert(make_pair(id,student));
栈(stack)
1.定义:
栈是一种只能在某一端插入和删除数据的特殊线性表。他按照先进先出的原则存储数据,先进的数据被压入栈底,最后进入的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后被压入栈的,最先弹出)。因此栈也称先进后出表。
允许进行插入删除操作的一端称为栈顶,另一端称为栈底。栈底固定,栈顶浮动。插入元素称为进栈,删除一个元素称为进栈,栈内元素为零称为空栈。
2.stack成员函数
bool empty ( ) ————>栈为空返回true,否则返回false;
void pop ( ) ————>删除栈顶元素,出栈;
void push(const TYPE&value)————> 插入新元素value,放置在栈顶进栈;TYPE:类型int,char…;
size_type size ( ) ————> 返回堆栈中元素个数;(注意注意!!!!切不可赋值给int ,很容易超过int的范围
TYPE&top()————> 查看当前栈顶元素;
List
定义:List类表示可通过索引访问的对象的强类型列表,提供用于对列表进行搜索、排序和操作的方法。
作用:
泛型最常见的用途是泛型集合
我们在创建列表类时,列表项的数据类型可能是int,string或其它类型,如果对列表类的处理方法相同,
就没有必要事先指定数据类型,留待列表类实例化时再指定。相当于把数据类型当成参数,这样可以最
大限度地重用代码,保护类型的安全以及提高性能。
定义 list<类型> 名称
成员函数
l.begin() 将迭代器返回到开头(Return iterator to beginning)
l.end() 将迭代器返回到最后(Return iterator to end)
l.rbegin() Return reverse iterator to reverse beginning
l.rend() Return reverse iterator to reverse end
l.l.empty() 检查容器是否为空
l.size() 返回当前容器内元素个数
l.max_size() 返回当前容器能容纳的最大元素数量
l.front() 访问第一个元素
l.back() 访问最后一个元素
l.push_front() 将元素插入到开头
l.pop_front() 删除第一个元素
l.push_back() 将元素插入到最后
l.pop_back() 删除最后一个元素
l.insert() 插入元素
l.erase() 删除元素
l.swap() 交换两个 list 内容
l.resize ()改变容器大小
l.clear() 删除容器所有内容
bitset
bitset可看作一个多位二进制数,每8位占用1个字节,相当于采用了状态压缩的二进制数组,并支持基本的位运算。一般以32位整数的运算次数为基准估算运行时间,n位bitset执行一次的位运算复杂度可视为n/32,效率较高。头文件< bitset >。
同样具有~,&,|,^,<<,>>操作符,==,!=可比较二进制数是否相等
bitset<10000> q; //声明一个10000位的二进制数
q[k] //表示q的第k位,可取值,赋值,最低位为q[0]
q.count() //返回有多少位1
q.none() //所有位都为0则返回true,至少1位为1则返回false
q.any() //所有位都为0则返回false,至少1位为1则返回true,与函数none相反
q.set() //把所有位变为1
q.set(k,v) //把第k位变为v,即q[k]=v
q.reset() //把所有位变为0
q.reset(k) //把第k位变为0,即q[k]=0
q.flip() //把所有位取反,即s=~s
q.flip(k) //把第k位取反,即q[k]^=1
疯子的算法总结(三) STL Ⅱ迭代器(iterator) + 容器相关推荐
- C++中的迭代器(STL迭代器)iterator
1.Cpp中的迭代器 要访问顺序容器和关联容器中的元素,需要通过迭代器(iterator)进行.迭代器是一个变量,相当于容器和操纵容器的算法之间的中介.迭代器可以指向容器中的某个元素,通过迭代器就可以 ...
- STL迭代器iterator
一:迭代器原理 迭代器是一个"可遍历STL容器内全部或部分元素"的对象. 迭代器指出容器中的一个特定位置. 迭代器就如同一个指针. 迭代器提供对一个容器中的对象的访问方法,并且可以 ...
- 疯子的算法总结(二) STL Ⅰ 算法 ( algorithm )
写在前面: 为了能够使后续的代码具有高效简洁的特点,在这里讲一下STL,就不用自己写堆,写队列,但是做为ACMer不用学的很全面,我认为够用就好,我只写我用的比较多的. 什么是STL(STl内容): ...
- STL源码剖析 迭代器iterator的概念 和 traits编程技法
iterator模式定义如下:提供一种方法,使之能够依序巡访某个 聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表述方式. STL的中心思想在于:将数据容器(containers)和算法(a ...
- mysql迭代器_迭代器是什么,C++ STL迭代器(iterator)用法详解
无论是序列容器还是关联容器,最常做的操作无疑是遍历容器中存储的元素,而实现此操作,多数情况会选用"迭代器(iterator)"来实现.那么,迭代器到底是什么呢? 我们知道,尽管不同 ...
- C++ 笔记(19)— 标准模板库(STL容器、STL迭代器、STL算法、STL容器特点、STL字符串类)
C++ 标准库可以分为两部分: 标准函数库: 这个库是由通用的.独立的.不属于任何类的函数组成的.函数库继承自 C 语言. 面向对象类库: 这个库是类及其相关函数的集合. C++ 标准库包含了所有的 ...
- stl变易算法(三)
本篇接着前面stl变易算法(一)和stl变易算法(二)继续讲述变易算法.这里将介绍完余下的变易算法,主要有:填充fill.n次填充fill_n.随机生成元素generate.随机生成n个元素gener ...
- STL迭代器(iterator)用法详解
C++ STL迭代器(iterator)用法详解 无论是序列容器还是关联容器,最常做的操作无疑是遍历容器中存储的元素,而实现此操作,多数情况会选用"迭代器(iterator)"来实 ...
- java 实现斐波切纳数列,求解这个算斐波切纳兔子有关问题的算法错哪了(和stl迭代器貌似有点关系)...
求解这个算斐波切纳兔子问题的算法哪里错了(和stl迭代器貌似有点关系) #include #include #include #define BORN_AGE 3 #define DIE_AGE 12 ...
最新文章
- 在NVIDIA Jetson Xavier NX上把yolov4-deepsort的模型pb模型使用tensorflow-onnx和onnx-tensorrt工具最终转换为tensorrt模型
- 源自KPI交谈的思考
- 蓝桥 算法训练 P0505
- 【报告分享】2021上半年短视频及电商生态研究报告.pdf(附下载链接)
- python excel处理模块_Python(00):openpyxl模块处理Excel文件
- fifaol4服务器维护,新闻|FIFAOL4 5月7日停机维护公告
- java 中super_Java中的super
- linux+时间戳+ns,时间戳转换工具
- 网站2008服务器32位好还是64位好,win server 2008 32位与64位区别
- 文件管理android2.3,ES文件浏览器(ES File Explorer)v4.0.2.3 优化版-好用的安卓文件管理器...
- 产业分析:智能巡检机器人行业
- 微软project下载安装及激活教程
- libcurl 库的编译
- android 百度地图获取城市,Android 百度地图获取两点之间的距离和推荐的驾车路线...
- Java面向对象程序思想
- FICO-笔记_20211019_002
- 《李开复自传——世界因你不同》——试读章节pdf下载
- POI报表——模板打印 AND 海量数据导出
- 不改一行代码,轻松拥有企业级微服务治理|MSE微服务治理专业版重磅发布
- zillow房价预测比赛_Zillow预测: 未来一年美国房价将大幅上涨!
热门文章
- Swift--字符串和字符(一)
- Atitti dbutil获取多个返回结果集的解决
- 浅谈C#中一种类插件系统编写的简单方法(插件间、插件宿主间本身不需要通信)...
- 安卓拒绝服务漏洞分析及漏洞检测
- Oracle命令(二):Oracle数据库几种启动和关闭方式
- 浅析C#合并多个WORD文档的具体实现方法
- 备份数据库的expdp语句_Oracle中利用expdp/impdp备份数据库的使用说明
- hibernate 双向一对多 关联在多端维护
- Eclipse RCP 中使用UTF8编码出现乱码问题的解决办法
- oracle查询cpu占用率高,ORACLE杀掉cpu占用率高的session