2.1STL的诞生
·长久以来,软件界一直希望建立一种可重复利用的东西
·C++的面向对象和泛型编程思想,目的就是复用性的提升
·大多情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作
·为了建立数据结构和算法的一套标准,诞生了STL
2.2STL基本概念
·STL(Standard Template Library,标准模板库)
·STL从广义上分为:容器(container)算法(algorithm)迭代器(iterator)
·容器和算法之间通过迭代器进行无缝连接
·STL几乎所有的代码都采用了模板或者模板函数
2.3STL六大组件
STL大体分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配置器)、空间适配器
1、容器:各种3数据结构,如vector、list、deaque、set、map等,用来存放数据。
2、算法:各种常用的算法,如sort、find、copy、for_each等
3、迭代器:扮演了容器与算法之间的胶合剂。
4、仿函数:行为类似函数,可作为算法的某种策略。
5、适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
6、空间配置器:负责空间的配置与管理。
2.4STL中容器、算法、迭代器
容器:置物之所也
STL容器就是将运用最广泛的一些数据结构实现出来
常用的数据结构:数组,链表,树,栈,队列,集合,映射表,等
这些容器分为序列式容器和关联式容器两种:
序列式容器:强调值得排序,序列式容器中的每个元素均有固定的位置
关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
算法:问题之解决也
有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Alogorithms)
算法分为:质变算法和非质变算法。
质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等
非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等
算法:问题之解决也
有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms)
算法分为:质变算法和非质变算法。
质变算法:是指运算过程中会更改区间的元素的内容。例如拷贝,替换,删除等等
非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等
迭代器:容器和算法之间粘合剂
提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。
每个容器都有自己专属的迭代器
迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针
常用的容器中迭代器种类为双向迭代器,和随机访问迭代器
2.5容器算法迭代器初始
了解STL中容器、算法、迭代器概念之后,我们利用代码感受STL的魅力
STL中最常见用的容器为vector,可以理解为数组,下面我们将学习如何向这个容器中插入数据,并遍历这个容器
2.5.1vector存放内置数据类型
容器:vector
算法:for_each
迭代器:vector<int>::iterator
2.5.2 Vector存放自定义数据类型
学习目标:vector中存放自定义数据类型,并且打印输出
2.5.3 Vector容器嵌套容器
学习目标:容器中嵌套容器,我们将所有数据进行遍历输出
3.1.1 string基本概念
本质:
·string是C++风格的字符串,而string本质是一个类
string和char*区别:
·char*是一个指针
·string是一个类,类内部封装了char*,管理这个字符串是一个char*型的容器。
特点:
string类内封装了很多成员方法
例如:查找find,拷贝copy,删除delete替换replace,插入insert
string管理char*所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责
3.1.2string构造函数
总结:string的多种构造方式没有可比性,灵活使用即可
3.1.3string赋值操作
功能描述:
·给string字符串进行赋值
赋值的函数原型:
总结 :
string的赋值方式很多,operator=这种方式是比较实用的
3.1.4string字符串拼接
功能描述:
·实现在字符串末尾拼接字符串
函数原型:
·string& operator+=(const char* str)//重载+=操作符
·string& operator+=(const char c);//重载+=操作符
·string& operator+=(const string& str);//重载+=操作符
·string& append(const char* s);//把字符串s连接到当前字符串结尾
·string& append(const char* s,int n);//把字符串s的前n个字符连接到当前字符串结尾
·string& append(const string &s);//同operator+=(const string& str)
`stringI& append(const string& s,int pos,int n);//字符串s中从pos开始的n个字符连接到字符串结尾
总结:字符串拼接的重载版本很多,初学阶段记住几种即可
3.1.5 string 查找和替换
功能描述:
·查找:查找指定字符串是否存在
·替换:在指定的位置替换字符串
函数原型:
·int find(const string& str,int pos=0) const;//查找str第一次出现位置,从pos开始查找
·int find(const char* s,int pos=0) const;//查找s第一次出现位置,从pos开始查找
·int find(const char* s,int pos,int n) const;//从pos位置查找s的前n个字符第一次位置
·int find(const char c,int pos=npos) const;//查找字符c第一次出现位置
·int rfind(const string& str,int pos=npos) const;//查找str 最后一次位置,从pos开始查找
·int rfind(const char* s,int pos=npos) const;//查找s 最后一次位置,从pos开始查找
·int rfind(const char* s,int pos,int n)const;//从pos查找s的前n个字符最后一次位置
·int rfind(const char c,int pos=0) const;//查找字符c最后一次出现位置
·string& replace(int pos,int n,const string& str);//替换从pos开始n个字符为字符串str
·string& replace(int pos,int n,const char* s);//替换从pos开始的n个字符为字符串s
总结:
·find查找是从左往右,rfind从右往左
·find找到字符串后返回查找的第一个字符位置,找不到返回-1
·replace在替换时,要指定从哪个位置起,多少个字符,替换成什么样的字符串
3.1.6 string字符串比较
功能描述:
·字符串之间的比较
比较方式:
·字符串比较是按字符的ASCLL码进行对比
=返回· 0
>返回 1
<返回 -1
函数原型:
·int compare(const string& s)const;//与字符串s比较
·int compare(const char* s)const;//与字符串s比较
总结:字符串对比主要用于比较两个字符串是否相等,判断谁大谁小的意义并不是很大
3.1.7string 字符存取
string中单个字符存取方式有两种
·char& operator[](int n);//通知[]方式取字符
·char& at(int n);//通过at方法获取字符
总结:string字符串中单个字符存取有两种方式,利用[]或at
3.1.8string插入和删除
功能描述:
·对string字符串进行插入和删除字符操作
函数原型:
·string& insert(int pos,const char* s);//插入字符串
·string& inrsert(int pos,const string& str);//插入字符串
·string& erase(int pos,int n=npos);//删除从Pos开始的n个字符
总结:插入和删除的起始下标都是从0开始
3.1.9string子串
功能描述:
·从字符串中获取想要的子串
函数原型:
·string substr(int pos=0,int n=npos)const;//返回由pos开始的n个字符组成的字符串
总结:灵活的运用求子串功能,可以在实际开发中获取有效信息
3.2 vector容器
3.2.1 vector基本概念
功能:
·vector数据结构和数组非常相似,也称为单端数组
vector与普通数组区别:
·不同之处在于数组是静态空间,而vector可以动态扩展
动态扩展:
·并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
·vector容器的迭代器是支持随机访问的迭代器
3.2.2 vector构造函数
功能描述:
·创建vector容器
函数原型:
·vector<T>v;//采用模板实现类,实现默认构造函数
·vector(v.begin(),v.end());//将v[begin(),end()]区间中的元素拷贝给本身
·vector(n,elem);//构造函数将n个elem拷贝给本身
·vector(const vector &vec)//拷贝构造函数
总结:vector的多种构造方式没有可比性,灵活使用即可
3.2.3 vector赋值操作
功能描述:
·给vector容器进行赋值
函数原型:
·vector& operator=(const vector &vec);//重载等号操作符
·assign(beg,end);//将[beg,end]区间中的数据拷贝赋值给本身
·assgin(n,elem);//将n个elem拷贝赋值给本身
总结:vector赋值方式比较简单,使用operator=,或者assign都可以
3.2.4 vector容器和大小
·对vector容器的容量的大小操作
函数原型:
·empty();//判断容器是否为空
·capacity();//容器的容量
·size();//返回容器中元素的个数
·resize(int num,elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除
总结:
·判断是否为空---empty
·返回元素个数---size
`返回容器容量---capacity
`重新指定大小---resize
3.2.5 vector插入和删除
功能描述:
·对vector容器进行插入、删除操作
函数原型:
·push_back(ele);//尾部插入元素ele
·pop_back();//删除最后一个元素
·insert(const_iterator pos,ele);//迭代器指向位置pos插入元素ele
·insert(const_iterator pos,int count,ele);//迭代器指向位置pos插入count个元素ele
·erase(const_iterator pos);//删除迭代器指向的元素
·erase(const_iterator start,const_iterator end);//删除迭代器从start到end之间的元素
·clear();//删除容器中所有元素
总结:
`尾插--push_back
`尾删---pop_back
`插入---insert(位置迭代器)
·删除---erase(位置迭代器)
·清空---clear
3.2.6 vector数据存储
功能描述:
·对vector中的数据的存取操作
函数原型:
·at(int idx);//返回索引idx所指的数据
·operator[];//返回索引idx所指的数据
·front();//返回容器中第一个数据元素
·back();//返回容器中最后一个数据元素
总结:
·除了用迭代器获取vector容器中元素,[]和at也可以
·front返回容器第一个元素
·back返回容器最后一个元素
3.2.7 vector互换容器
功能描述:
·实现两个容器内元素进行互换
函数原型:
·swap(vec);//将vec与本身的元素互换
总结;swap可以使两个容器互换,可以达到实用的收缩内存效果
3.2.8 vector预留空间
功能描述:
·减少vector在动态扩展容量时的扩展次数
函数原型:
·reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问。
总结:如果数据量较大,可以一开始利用reserve预留空间
3.3 deque容器
3.3.1 deque容器基本概念
功能:
·双端数组,可以对头端进行插入删除操作
deque与vector区别:
·vector对于头部的插入删除效率低,数据量大,效率越低
·deque相对而言,对头部的插入删除速度会比vector快
·vector访问元素时的速度会比deque快,这和两者内部实现有关
deque内部工作原理:
deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
·deque容器的迭代器也是支持随机访问的
3.2.2 deque构造函数
功能描述;
·deque容器构造
函数原型:
·deque<T>deqT;//默认构造形式
·deque(beg,end);//构造函数将[beg,end)区间中的元素拷贝给本身。
·deque(n,elem);//构造函数将n个elem拷贝给本身。
·deque(const deque &deq);//拷贝构造函数
总结:deque容器和vector容器的构造方式几乎一致,灵活使用即可beg
3.3.3 deque赋值操作
功能描述:
·给deque容器进行赋值
函数原型:
·deque&-operator=(const deque &deq);//重载等号操作符
·assgin(beg,end);//将[beg,end)区间中的数据拷贝赋值给本身
·assign(n,elem);//将n个elem拷贝赋值给本身
总结:deque赋值操作也与vector相同,需熟练掌握
3.3.4 deque大小操作
功能描述:
·对deque容器的大小进行操作
函数原型:
·deque.empty();//判断容器是否为空
·deque.size();//返回容器中元素个数
·deque.resize(num);//重新指定容器的长度为num,若容器变长,则默认值填充新位置
//如果容器变短,则末尾超出容器长度的元素被删除
·deque.resize(num,elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置
//如果容器变短,则末尾超出容器长度的元素被删除。
总结:
·deque没有容量的概念
·判断是否为空---empty
·返回元素个数---size
·重新指定个数---resize
3.3.5 deque插入和删除
功能描述:
·向deque容器插入和删除数据
函数原型:
两端插入操作:
·push_back(elem);//在容器尾部添加一个数据
·push_front(elem);//在容器头部插入一个数据
·pop_back();//删除容器最后一个数据
·pop_front();//删除容器第一个数据
指定位置操作:
·insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置。
·insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
`insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
·clear();//清空容器的所有数据
·erase(beg,end);//删[beg,end)区间的数据,返回下一个数据的位置
·erase(pos);//删除pos位置的数据,返回下一个数据的位置
总结:
·插入和删除提供的位置是迭代器!
·尾插---push_back
·尾删---pop_back
·头删---pup_front
·头删---pop_front
3.3.6 deque数据存取
功能描述:
·对deque中的数据的存取操作
函数原型:
·at(int idx);//返回索引idx所指的数据
·operator[];//返回索引idx所指的数据
·front();//返回容器中第一个数据元素
·back();//返回容器中最后一个数据元素
总结:
·除了用迭代器获取deque容器中元素,[]和at也可以
`front返回容器第一个元素
·back返回容器最后一个元素
3.3.7 deque排序
功能描述:
·利用算法实现对deque容器进行排序
算法:
·sort(iterator beg,iterator end)//对beg和end区别内元素进行排序
总结:sort算法非常实用,使用时包含头文件algorithm即可
3.4案例-评委打分
3.4.1案例描述
有5名选手:ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。
3.4.2实现步骤
1、创建五名选手,放到vector中
2、遍历vector容器,取出来每一个选手,执行for循环,可以把10个评分打分存到deque容器中
3、sort算法对deque容器中分数排序,去除最高分和最低分
4、deque容器遍历一遍,累加总分
5、获取平均分
3.5 stack容器
3.5.1 stack基本概念
概念:stack是一种先进后出(First in Last Out,FILO)的数据结构,它只有一个出口
栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为
栈中进数据称为---入栈push
栈中弹出数据称为---出栈 pop
3.5.2 stack 常见接口
功能描述:栈容器常用的对外接口
构造函数:
·stack<T> stk;//stack采用模板类实现,stack对象的默认构造形式
·stack(const stack &stk);//拷贝构造函数
赋值操作:
·stack& operator=(const stack& stk);//重载等号操作符
数据存取:
·push(elem);//向栈顶添加元素
·pop();//从栈顶移除第一个元素
top();//返回栈顶元素
大小操作:
·empty();//判断堆栈是否为空
·size();//返回栈的大小
总结:
·入栈---push
·出栈---pop
·返回栈顶---top
·判断栈是否为空---empty
·返回栈大小---size
3.6 queue容器
3.6.1 queue基本概念
概念:Queue是一种先进先出(First In First Out,FIFO)的数据结构,它有两个出口
队列容器允许从一端新增元素,从另一端移除元素
队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为
队列中进数据称为---入队 push
队列中出数据称为---出队 pop
3.6.2 queue 常见接口
功能描述:栈容器常用的对外接口
构造函数:
·queue<T> que;//queue采用模板类实现,queue对象的默认构造形式
·queue(const queue& que);//拷贝构造函数
赋值操作:
·queue& operator=(const queue& que);//重载等号操作符
数据存取:
·push(elem);//往队尾添加元素
·pop();//从队头移除第一个元素
·back();//返回最后一个元素
·front();//返回第一个元素
大小操作:
·empty();//判断堆栈是否为空
·size();//返回栈的大小
总结:
·入队---push
·出队---pop
·返回队头元素---front
·返回队尾元素---back
·判断队是否为空---empty
· 返回队列大小---size
3.7 list容器
3.7.1 list基本概念
功能:将数据进行链式存储
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
链表的组成:链表由一系列结点组成
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
STL中的链表是一个双向循环链表
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
list的优点:
·采用动态存储分配,不会造成内存浪费和溢出
·链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
list的缺点:
·链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大
List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。
总结:STLList和vector是两个最常被使用的容器,各有优缺点
3.7.2list构造函数
功能描述:
·创建list容器
函数原型:
·list<T>lst;//list采用模板类实现,对象的默认构造形式;
·list(beg,end);//构造函数将[beg,end)区间中的元素拷贝给本身。
·list(n,elem);//构造函数将n个elem拷贝给本身。
·list(const list &lst);//拷贝构造函数。
总结:list构造方式同其他几个STL常用容器,熟练掌握即可
3.7.3list赋值和交换
功能描述:
·给list容器进行赋值,以及交换list容器
函数原型:
·assgin(beg,end);//将[beg,end);//将[beg,end)区间中的数据拷贝赋值给本身
·assign(n,elem);//将n个elem拷贝赋值给本身
·list& operator=(const list &lst);//重载等号操作符
·swap(list);//将lst与本身的元素交换
总结:list赋值和交换操作能够灵活运用即可
3.7.4list大小操作
功能描述:
·对list容器大小进行操作
函数原型:
·size();//返回容器中元素的个数
·empty();//判断容器是否为空
·resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置
//如果容器变短,则末尾超出容器长度的元素被删除。
·resize(num,elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。
//如果容器变短,则末尾超出容器长度的元素被删除。
总结:
·判断是否为空---empty
·返回元素个数---size
·重新指定个数---resize
3.7.5 list插入和删除
功能描述:
·对list容器进行数据的插入和删除
函数原型:
·push_back(elem);//在容器尾部加入一个元素
·pop_back();//删除容器中最后一个元素
·push_front(elem);//在容器开头插入一个元素
·pop_front();//从容器开头移除第一个元素
·insert(pos,elem);//在pop位置插elem元素的拷贝,返回新数据的位置
·insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
·insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。
·clear();//移除容器的所有数据
·erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
·erase(pos);//删除pos位置的数据,返回下一个数据的位置
·remove(elem);//删除容器中所有与elem值匹配的元素。
总结:
·尾插---push_back
·尾删---pop_back
·头插---push_front
·头删---push_back
·插入---insert
·删除---erase
·移除---remove
·清空---clear
3.7.6 list数据存取
功能描述:
·对list容器中数据进行存取
函数原型:
·front();//返回第一个元素
·back();//返回最后一个元素
总结:
·list容器中不可以通过[]或者at方式访问数据
·返回第一个元素---front
`返回最后一个元素---back
3.7.7 list反转和排序
功能描述:
·将容器中的元素反转,以及将容器中的数据进行排序
函数原型:
·reverse();//反转链表
·sort();//链表排序
总结:
·反转---reverse
·排序---sort(成员函数)
3.7.8 排序案例
案例描述:将Person自定义数据类型进行排序,Perosn中属性有姓名、年龄、身高
排序规则:按年龄进行升序、如果年龄相同按照身高进行排序
总结:
·对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
·高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂
3.8 set/multiset容器
3.8.1 set基本概念
简介:
·所有元素都会在插入时自动被排序
本质:
·set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multise区别:
·set不允许容器中有重复的元素
·multiset允许容器中有重复的元素
3.8.2 set构造和赋值
功能描述:创建set容器以及赋值
构造:
·set<T>st;//默认构造函数;
·set(const set &st);//拷贝构造函数
赋值:
·set& operator=(const set &st);//重载等号操作符
总结:
·set容器插入数据时用insert
·set容器插入数据的数据会自动排序
3.8.3 set大小和交换
功能描述:
·统计set容器大小以及交换set容器
函数原型:
·size();//返回容器中元素的数目
·empty();//判断容器是否为空
·swap(st);//交换两个集合容器
总结:
·统计大小--size
`判断是否为空---empty
·交换容器---swap
3.8.4 set插入和删除
功能描述:
· set容器进行插入数据和删除数据
函数原型:
·insert(elem);//在容器中插入元素
·clear();//清除所有元素
·erase(pos);//删除pos迭代器所指的元素,返回下一个元素迭代器。
·erase(beg,end);//删除区间[beg,end)的所有元素,返回下一个元素的迭代器。
·erase(elem);//删除容器中值为elem的元素
总结:
·插入---insert
·删除---erase
·清空---clear
3.8.5 set查找和统计
功能描述:
·对set容器进行查找数据以及统计数据
函数原型:
·find(key);//查找key是否存在,若存在,返回该键的元素的迭代器,若不存在返回set.end();
·count(key);//统计key的元素个数
总结:
·查找---find(返回的是迭代器)
·统计---count(对于set,结果为0或者1)
3.8.6 set和multiset的区别
区别:
·set不可以插入重复数据,而multiset可以
·set插入数据的同时会返回插入结果,表示插入是否成功
·multiset不会检测数据,因此可以插入重复数据
总结:
·如果不允许插入重复数据可以利用set
·如果需要插入重复数据利用multiset
3.8.7 pair对组创建
功能描述:
·成对出现的数据,利用对组可以返回两个数据
两种创建方式:
·pair<type,type>p(value1,value2);
·pair<type,type>p=make_pair(value1,value2);
总结:
两种方式都可以创建数组,记住一种即可
3.8.8 set容器排序
学习目标:
·set容器默认排序规则为从小到大,掌握如何改变排序规则
主要技术点:
·利用仿函数。可以改变排序规则
示例一 set存放内置数据类型
总结:利用仿函数可以指定set容器的排序规则
示例二:set存放自定义数据类型
总结:对于自定义数据类型,set必须指定排序规则才可以插入数据
3.9map/multimap
3.9.1map基本概念
简介:
·map中所有元素都是pair
·pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
·所有元素都会根据元素的键值自动排序
本质:
·map/multimap属于关联式容器,底层结构是用二叉树实现
优点:
·可以根据key值快速找到value值
map和multimap区别:
·map不允许容器中有重复key元素
·multimap允许容器中有重复key值元素
3.9.2 map构造和赋值
功能描述:
·对map容器进行构造和赋值操作
函数原型:
构造:
·map<T1,T2>mp;//map默认构造函数;
·map(const map &mp);//拷贝构造函数
赋值:
·map& operator=(const map &mp);//重载等号操作符
总结:map中所有元素都是成对出现,插入数据时候要使用对组
3.9.3 map大小和交换
功能描述:
·统计map容器以及交换map容器
函数原型:
·size();//返回容器中元素的数目
·empty();//判断容器是否为空
·swap(st);//交换两个集合容器
总结:
·统计大小---size
·判断是否为空---empty
·交换容器---swap
3.9.4 map插入和删除
·map容器进行插入数据和删除数据
函数原型:
·insert(elem);//在容器中插入元素。
·clear();//清除所有元素
·erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end);//删除区间[beg,end)的所有元素,返回下一个元素的迭代器。
·erase(key);//删除容器中值为key的元素。
总结:
·map插入方式很多,记住其一即可
·插入---insert
·删除---erase
·清空---clear
3.9.5 map查找和统计
功能描述:
·对map容器进行查找数据以及统计数据
函数原型:
·find(key);//查找key是否存在,返回该键的元素的迭代器,若不存在,返回map.end();
·count(key);//统计key的元素个数
总结:
·查找---find(返回的是迭代器)
·统计---count(对于map,结果为0或者为1)
3.9.6 map容器排序
学习目标:
·map容器默认排序规则为按照key值进行从小到大排序,掌握如何改变排序规则
主要技术点:
·利用仿函数,可以改变排序规则
总结:
·利用仿函数可以指定map容器的排序规则
·对于自定义数据类型,map必须要指定排序规则,同set容器
3.10案例-员工分组
3.10.1 案例描述
·公司今天招聘了10个员工(ABCDEFGHIJ),10名员工进入公司之后,需要指派员工在那个部门工作
·员工信息有:姓名 工资组成:部门分为:策划、美术、研发
·随机给10个员工分配部门和工资
·通过multimap进行信息的插入 key(部门编号)value(员工)
·分部门显示员工信息
3.10.2 实现步骤
1.创建10名员工,放到vector中
2.遍历vector容器,取出每个员工,进行随机分组
3.分组后,将员工部门编号作为key,具体员工作为value,放入到multimap容器中
4.分部门显示员工信息
4 STL-函数对象
4.1函数对象
4.1.1函数对象概念
概念:
·重载函数调用操作符的类,其对象称称为函数对象
·函数对象使用重载的()时,行为类似函数调用,也叫仿函数
本质:
函数对象(仿函数)是一个类,不是一个函数
4.1.2 函数对象使用
特点:
·函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
·函数对象超出普通函数的概念吗,函数对象可以有自己的状态
·函数对象可以作为参数传递
总结:
仿函数写法非常灵活,可以作为参数进行传递
4.2谓词
4.2.1谓词概念
概念:
·返回bool类型的仿函数称为谓词
·如果operator()接受一个参数,那么叫做一元谓词
·如果operator()接受两个参数,那么叫做二元谓词
总结:参数只有一个的谓词,称为一元谓词
总结:参数只有两个的谓词,称为二元谓词
4.3内建函数对象
4.3.1 内建函数对象意义
概念:
·STL内建了一些函数对象
分类:
·算术仿函数
·关系仿函数
·逻辑仿函数
用法:
·这些仿函数所产生的对象,需要引入头文件#include<functional>
4.3.2 算术仿函数
功能描述:
·实现四则运算
·其中negate是一元运算,其他都是二元运算
仿函数原型:
·template<class T>T pius<T>//加法仿函数
·template<class T>T minus<T>//减法仿函数
·template<class T>T multiplies<T>//乘法仿函数
·template<class T>T divides<T>//除法仿函数
·template<class T>T modulus<T>//取模仿函数
·template<class T>T negate<T>//取反仿函数
总结:使用内建函数对象时,需要引入头文件#include<functional>
4.3.3 关系仿函数
功能描述:
·实现关系对比
仿函数原型:
·template<class T>bool equal_to<T>//等于
·template<class T>bool not_equal_to<T>//不等于
·template<class T>bool greater<T>//大于
·template<class T>bool greater_equal<T>//大于等于
·template<class T> bool less<T> //小于
·template<class T> bool less_equal<T> //小于等于
总结:关系运算仿函数最常见的就是greater<>大于
4.3.4 逻辑仿函数
功能描述:
实现逻辑运算
函数原型:
·template<class T> bool logical_and<T> //逻辑与
·template<class T> bool logical_or<T> //逻辑或
·template<class T> bool logical_not<T> //逻辑非
总结:逻辑仿函数实际应用较少,了解即可
5 STL- 常用算法
概述:
-
算法主要是由头文件
<algorithm>
<functional>
<numeric>
组成。 -
<algorithm>
是所有STL头文件中最大的一个,范围涉及到比较、 交换、查找、遍历操作、复制、修改等等 -
<numeric>
体积很小,只包括几个在序列上面进行简单数学运算的模板函数 -
<functional>
定义了一些模板类,用以声明函数对象。
5.1 常用遍历算法
学习目标:
- 掌握常用的遍历算法
算法简介:
for_each
//遍历容器transform
//搬运容器到另一个容器中
5.1.1 for_each
功能描述:
- 实现遍历容器
函数原型:
-
for_each(iterator beg, iterator end, _func);
// 遍历算法 遍历容器元素
// beg 开始迭代器
// end 结束迭代器
// _func 函数或者函数对象
-
总结:for_each在实际开发中是最常用遍历算法,需要熟练掌握
-
5.1.2 transform
功能描述:
- 搬运容器到另一个容器中
-
函数原型:
transform(iterator beg1, iterator end1, iterator beg2, _func);
-
//beg1 源容器开始迭代器
//end1 源容器结束迭代器
//beg2 目标容器开始迭代器
//_func 函数或者函数对象
总结:搬运的目标容器必须要提前开辟空间,否则无法正常搬运
5.2 常用查找算法
学习目标:
- 掌握常用的查找算法
算法简介:
find
//查找元素find_if
//按条件查找元素adjacent_find
//查找相邻重复元素binary_search
//二分查找法count
//统计元素个数count_if
//按条件统计元素个数
5.2.1 find
功能描述:
- 查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()
函数原型:
-
find(iterator beg, iterator end, value);
// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
// beg 开始迭代器
// end 结束迭代器
// value 查找的元素
-
总结:利用find可以在容器中找到指定的元素,返回值是迭代器
5.2.2 find_if
功能描述:
- 按条件查找元素
函数原型:
-
find_if(iterator beg, iterator end, _Pred);
// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
// beg 开始迭代器
// end 结束迭代器
// _Pred 函数或者谓词(返回bool类型的仿函数)
-
5.2.3 adjacent_find
功能描述:
- 查找相邻重复元素
- 函数原型:
-
adjacent_find(iterator beg, iterator end);
// 查找相邻重复元素,返回相邻元素的第一个位置的迭代器
// beg 开始迭代器
// end 结束迭代器
-
总结:面试题中如果出现查找相邻重复元素,记得用STL中的adjacent_find算法
5.2.4 binary_search
功能描述:
- 查找指定元素是否存在
函数原型:
-
bool binary_search(iterator beg, iterator end, value);
// 查找指定的元素,查到 返回true 否则false
// 注意: 在无序序列中不可用
// beg 开始迭代器
// end 结束迭代器
// value 查找的元素
总结:二分找法查找效率很高,值得注意的是查找的容器中元素必须的有序序列
5.2.5 count
功能描述:
- 统计元素个数
函数原型:
-
count(iterator beg, iterator end, value);
// 统计元素出现次数
// beg 开始迭代器
// end 结束迭代器
// value 统计的元素
总结:统计自定义数据类型时候,需要配合重载operator==
5.2.6 count_if
功能描述:
- 按条件统计元素个数
函数原型:
-
count_if(iterator beg, iterator end, _Pred);
// 按条件统计元素出现次数
// beg 开始迭代器
// end 结束迭代器
// _Pred 谓词
总结:按值统计用count,按条件统计用count_if
5.3 常用排序算法
学习目标:
- 掌握常用的排序算法
算法简介:
sort
//对容器内元素进行排序random_shuffle
//洗牌 指定范围内的元素随机调整次序merge
// 容器元素合并,并存储到另一容器中reverse
// 反转指定范围的元素
5.3.1 sort
功能描述:
- 对容器内元素进行排序
函数原型:
-
sort(iterator beg, iterator end, _Pred);
// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
// beg 开始迭代器
// end 结束迭代器
// _Pred 谓词
总结:sort属于开发中最常用的算法之一,需熟练掌握
5.3.2 random_shuffle
功能描述:
- 洗牌 指定范围内的元素随机调整次序
函数原型:
-
random_shuffle(iterator beg, iterator end);
// 指定范围内的元素随机调整次序
// beg 开始迭代器
// end 结束迭代器
总结:random_shuffle洗牌算法比较实用,使用时记得加随机数种子
5.3.3 merge
功能描述:
- 两个容器元素合并,并存储到另一容器中
函数原型:
-
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
// 容器元素合并,并存储到另一容器中
// 注意: 两个容器必须是有序的
// beg1 容器1开始迭代器
-
// end1 容器1结束迭代器
-
// beg2 容器2开始迭代器
-
// end2 容器2结束迭代器
-
// dest 目标容器开始迭代器
总结:merge合并的两个容器必须的有序序列
5.3.4 reverse
功能描述:
- 将容器内元素进行反转
函数原型:
-
reverse(iterator beg, iterator end);
// 反转指定范围的元素
// beg 开始迭代器
// end 结束迭代器
总结:reverse反转区间内元素,面试题可能涉及到
5.4 常用拷贝和替换算法
学习目标:
- 掌握常用的拷贝和替换算法
算法简介:
copy
// 容器内指定范围的元素拷贝到另一容器中replace
// 将容器内指定范围的旧元素修改为新元素replace_if
// 容器内指定范围满足条件的元素替换为新元素swap
// 互换两个容器的元素
5.4.1 copy
功能描述:
- 容器内指定范围的元素拷贝到另一容器中
函数原型:
-
copy(iterator beg, iterator end, iterator dest);
// 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
// beg 开始迭代器
// end 结束迭代器
// dest 目标起始迭代器
总结:利用copy算法在拷贝时,目标容器记得提前开辟空间
5.4.2 replace
功能描述:
- 将容器内指定范围的旧元素修改为新元素
函数原型:
-
replace(iterator beg, iterator end, oldvalue, newvalue);
// 将区间内旧元素 替换成 新元素
// beg 开始迭代器
// end 结束迭代器
// oldvalue 旧元素
// newvalue 新元素
总结:replace会替换区间内满足条件的元素
5.4.3 replace_if
功能描述:
- 将区间内满足条件的元素,替换成指定元素
函数原型:
-
replace_if(iterator beg, iterator end, _pred, newvalue);
// 按条件替换元素,满足条件的替换成指定元素
// beg 开始迭代器
// end 结束迭代器
// _pred 谓词
// newvalue 替换的新元素
总结:replace_if按条件查找,可以 利用仿函数灵活筛选满足的条件
5.4.4 swap
功能描述:
- 互换两个容器的元素
函数原型:
-
swap(container c1, container c2);
// 互换两个容器的元素
// c1容器1
// c2容器2
总结:swap交换容器时,注意交换的容器要同种类型
5.5 常用算术生成算法
学习目标:
- 掌握常用的算术生成算法
注意:
- 算术生成算法属于小型算法,使用时包含的头文件为
#include <numeric>
算法简介:
-
accumulate
// 计算容器元素累计总和 -
fill
// 向容器中添加元素
5.5.1 accumulate
功能描述:
- 计算区间内 容器元素累计总和
函数原型:
函数原型:
-
accumulate(iterator beg, iterator end, value);
// 计算容器元素累计总和
// beg 开始迭代器
// end 结束迭代器
// value 起始值
-
总结:accumulate使用时头文件注意是numeric,这个算法很实用
-
5.5.2 fill
功能描述:
- 向容器中填充指定的元素
- 函数原型:
-
fill(iterator beg, iterator end, value);
// 向容器中填充元素
// beg 开始迭代器
// end 结束迭代器
// value 填充的值
-
总结:利用fill可以将容器区间内元素填充为 指定的值
-
5.6 常用集合算法
学习目标:
- 掌握常用的集合算法
-
算法简介:
-
set_intersection
// 求两个容器的交集 -
set_union
// 求两个容器的并集 -
set_difference
// 求两个容器的差集
5.6.1 set_intersection
功能描述:
- 求两个容器的交集
-
set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
// 求两个集合的交集
// 注意:两个集合必须是有序序列
// beg1 容器1开始迭代器
-
// end1 容器1结束迭代器
-
// beg2 容器2开始迭代器
-
// end2 容器2结束迭代器
-
// dest 目标容器开始迭代器
-
总结:
-
求交集的两个集合必须的有序序列
-
目标容器开辟空间需要从两个容器中取最小值
-
set_intersection返回值既是交集中最后一个元素的位置
5.6.2 set_union
功能描述:
- 求两个集合的并集
函数原型:
-
set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
// 求两个集合的并集
// 注意:两个集合必须是有序序列
// beg1 容器1开始迭代器
-
// end1 容器1结束迭代器
-
// beg2 容器2开始迭代器
-
// end2 容器2结束迭代器
-
// dest 目标容器开始迭代器
-
总结:
-
求并集的两个集合必须的有序序列
-
目标容器开辟空间需要两个容器相加
-
set_union返回值既是并集中最后一个元素的位置
-
5.6.3 set_difference
功能描述:
- 求两个集合的差集
- 函数原型:
-
set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
// 求两个集合的差集
// 注意:两个集合必须是有序序列
// beg1 容器1开始迭代器
-
// end1 容器1结束迭代器
-
// beg2 容器2开始迭代器
-
// end2 容器2结束迭代器
-
// dest 目标容器开始迭代器
-
-
总结:
-
求差集的两个集合必须的有序序列
目标容器开辟空间需要从两个容器取较大值
set_difference返回值既是差集中最后一个元素的位置