文章目录
C++提高编程
1 STL初识
1.1 STL的诞生
- 长久以来,软件界一直希望建立一种可重复利用的东西
- C++的面向对象和泛型编程思想,目的就是复用性的提升
- 大多情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作
- 为了建立数据结构和算法的一套标准,诞生了STL
1.2 STL基本概念
- STL(Standard Template Library, 标准模板库)
- STL从广义上分为容器(container)算法(algorithm)迭代器(iterator)
- 容器和算法之间通过迭代器进行无缝连接
- STL几乎所有的代码都采用了模板类或者模板函数
1.3 STL六大组件
-
容器
各种数据结构,如vector、list、deque、set、map等,用来存放数据
-
算法
各种常用的算法,如sort、find、copy、for_each等
-
迭代器
扮演了容器与算法之间的胶合剂
-
仿函数
行为类似函数,可作为算法的某种策略
-
适配器(配接器)
一种用来修饰容器或者仿函数或迭代器接口的东西
-
空间配置器
负责空间配置与管理
1.4 STL中容器、算法、迭代器
-
容器:置物之所也
- STL容器就是将运用最广泛的一些数据结构实现出来
- 常用的数据结构:数组、链表、树、栈、队列、集合、映射表 等
- 这些容器分为序列式容器和关联式容器:
- 序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置。
- 关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
-
算法:问题之解法也
- 有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms)
- 算法分为:质变算法和非质变算法
- 质变算法:是指运算过程中会更改区间内的元素的内容。例如,拷贝,替换,删除等等
- 非质变算法:是指运算过程中不会更改区间内的元素内容:例如查找、计数、遍历、寻找极值等等
-
迭代器:容器和算法之间的粘合剂
-
提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式
-
每个容器都有自己专属的迭代器
-
迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针
-
迭代器种类
迭代器类别 说明 输入 对数据的只读访问 输出 对数据的只写访问 前向 读写操作,并能向前推荐迭代器 双向 读写操作,并能向前和向后操作 随机访问 读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器 常用的容器中迭代器种类为双向迭代器和随机访问迭代器
-
只有顺序容器和关联容器支持迭代器遍历,各容器支持的迭代器的类别如下:
容器 支持的迭代器类别 vector 随机访问 deque 随机访问 list 双向 set 双向 multiset 双向 map 双向 multimap 双向 stack 不支持 queue 不支持 priority_queue 不支持
-
1.5 容器算法迭代器初识
1.5.1 vector存放内置数据类型
-
容器:vector
-
算法:for_each
-
迭代器:vector ::iterator
-
示例代码
#include <vector> #include <algorithm> void MyPrint(int val) { cout << val << endl; } vodi test01() { //创建vector容器对象,并且通过模板参数指定容器中存放的数据的类型 vector<int> v; //向容器中放数据 v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); //每一个容器都有自己的迭代器,迭代器是用来遍历容器中的元素 //v.begin()返回迭代器,这个迭代器指向容器中第一个数据 //v.end()返回迭代器,这个迭代器指向容器元素的最后一个元素的下一个位置 //vector<int>::iterator 拿到vector<int>这种容器的迭代器类型 vector<int>::iterator pBegin = v.begin(); vector<int>::iterator pEnd = v.end(); //第一种遍历方式: while (pBegin != pEnd) { cout << *pBegin() << endl; pBegin++; } //第二种遍历方式: for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << endl; } //第三种遍历方式: //使用STL提供标准遍历算法 头文件 algorithm for_each(v.begin(), v.end(), MyPrint); } int main() { test01(); system("pause"); return 0; }
1.5.2 存放自定义数据类型
-
代码示例
#include <vector> #include <string> //自定义数据类型 class Person{ public: Person(string name, int age){ mName = name; mAge = age; } public: string mName; int mAge; }; //存放对象 void test01(){ vector<Person> v; //创建数据 Person p1("aaa", 10); Person p2("bbb", 20); Person p3("ccc", 30); Person p4("ddd", 40); Person p5("eee", 50); v.push_back(p1); v.push_back(p2); v.push_back(p3); v.push_back(p4); v.push_back(p5); for (vector<Person>::iterator it = v.begin();it != v.end(); it++){ cout << "Name: " << (*it).mName << "Age: " << it->mAge << endl; } } //放对象指针 void test02(){ vector<Person*> v; //创建数据 Person p1("aaa", 10); Person p2("bbb", 20); Person p3("ccc", 30); Person p4("ddd", 40); Person p5("eee", 50); v.push_back(&p1); v.push_back(&p2); v.push_back(&p3); v.push_back(&p4); v.push_back(&p5); for (vector<Person>::iterator it = v.begin();it != v.end(); it++){ cout << "Name: " << (*it)->mName << "Age: " << (*(*it)).mAge << endl; } } int main() { test01(); test02(); system("pause"); return 0; }
1.5.3 Vector容器嵌套容器
-
代码示例
#include <vector> //容器嵌套容器 void test01(){ vector<vector<int>> v; vector<int> v1; vector<int> v2; vector<int> v3; vector<int> v4; for (int i = 0; i < 4; i++){ v1.push_back(i+1); v2.push_back(i+2); v3.push_back(i+3); v4.push_back(i+4); } //将容器元素插入到vector v中 v.push_back(v1); v.push_back(v2); v.push_back(v3); v.push_back(v4); //遍历输出 v for(vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++) { for(vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++){ cout << *vit <<" "; } cout << endl; } } int main(){ test01(); system("pause"); return 0; }
2 STL-常用容器
2.1 string容器
2.1.1 string基本概念
- 本质:
- string是C++风格的字符串,而string本质上是一个类
- string和char*区别:
- char * 是一个指针
- string是一个类,类内部封装了char *,管理这个字符串,是一个char *型的容器
- 特点:
- string类内部封装了很多成员方法
- 例如:查找find,拷贝copy,删除delete,替换replace,插入insert
- string管理char*所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责
2.1.2 string构造函数
-
构造函数原型:
- string(); //创建一个空的字符串 例如:string str;
- string(const char* s); //使用字符串s初始化
- string(const string& str); //使用一个string对象初始化另一个string对象
- string(int n, char c); //使用n个字符c初始化
-
代码示例
#include <string> void test01() { string s1; //创建空字符串,调用无参构造函数 cout << "str = " << s1 << endl; const char* str = "hello,world"; string s2(str); //把c_string转换成了string cout << "str2 = " << s2 << endl; string s3(s2); //调用拷贝构造函数 cout << "str3 = " << s3 << endl; string s4(10, 'a'); cout << "str3 = " << s3 << endl;//打印出10个a } int main(){ test01(); system("pause"); return 0; }
-
总结:string的多种构造方式没有可比性,灵活使用即可
2.1.3 string赋值操作
-
功能描述:
给string字符串进行赋值
-
赋值的函数原型:
- string& operator = (const char *s); //char *类型字符串赋值给当前的字符串(=号)
- string& operator = (const string &s); //把字符串s赋给当前的字符串
- string& operator = (char c); //字符赋值给当前的字符串
- string& assign (const char *s); //把字符串s赋给当前的字符串(成员函数)
- string& assign (const char *s, int n); //把字符串s的前n个字符赋给当前的字符串
- string& assign (const string &s); //把字符串s赋给当前字符串
- string& assign(int n, char c); //用n个字符c赋给当前字符串
-
代码示例
void test01() { string str1; str1 = "hello world"; cout << " str1 = " << str1 << endll; string str2; str2 = str1; cout << " str2 = " << str2 << endll; string str3; str3 = 'a'; cout << " str3 = " << str3 << endll; string str4; str4.assign("hello c++") cout << " str4 = " << str4 << endll; string str5; str5.assign("hello c++", 5) cout << " str5 = " << str5 << endll; string str6; str6.assign(str5); cout << " str6 = " << str6 << endll; string str7; str7.assign(5, 'x'); cout << " str7 = " << str7 << endll; } int main(){ test01(); system("pause"); return 0; }
-
string的赋值方式很多,operator= 这种方式是比较实用的
2.1.4 string字符串拼接
- 功能描述:
- 实现在字符串末尾拼接字符串
- 函数原型:
- 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)
- string& append (const string &s, int pos, int n); //字符串s中从pos开始的n个字符连接到字符串结尾
2.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 = 0) const;//查找字符c第一次出现位置
- int rfind(const string& str, int pos = npos) const;//查找str最后一次位置,从pos开始查找
- int rfind(const * s, int pos = npos) const;//查找s最后一次出现位置,从pos开始查找
- int rfind(const * 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
-
代码示例
void test01() { //查找 string str1 = "abcdefgde"; int pos = str1.find("de"); if(pos == -1) { cout << "未找到" << endl; } else { cout << "pos = " << pos << endl; } //find 和 rfind区别,find从左往右找,rfind从右往左找 pos = str1.rfind("de"); cout << "pos = " << pos << endl; } void test02() { //替换 string str1 = "abcdefgde"; //从 1号位置起 3个字符 替换为"1111" str1.replace(1, 3, "1111"); cout << "str1 = " << str1 << endl; }
-
总结:
- find查找是从左往后,rfind从右往左
- find找到字符串后返回查找的第一个字符位置,找不到返回-1
- replace在替换时,要指定从哪个位置起,多少个字符,替换成什么样的字符串
2.1.6 string字符串比较
-
功能描述:
- 字符串之间的比较
-
比较方式
-
字符串比较是按字符的ASCII码进行对比
相等 返回 0
大于 返回 1
小于 返回 -1
-
-
函数原型:
- int compare(const string &s) const;//与字符串s比较
- int compare(const char *s) const;//与字符串s比较
2.1.7 string字符存取
-
string中单个字符存取方式有两种
- char& operator[] (int n)
- char &at(int n);
-
代码示例
void test01() { string str = "hello"; //1.通过 []访问单个字符 for(int i = 0; i < str.size(); i++) { cout << str[i] << " "; } cout << endl; //2.通过at方式访问单个字符 for (int i = 0; i < str.size(); i++) { cout << str.at(i) << " "; } cout << endl; //修改单个字符 str[0] = 'x'; str.at(1) = 'x'; cout << "str = " << str << endl; }
2.1.8 string插入和删除
- 功能描述:
- 对string字符串进行插入和删除操作
- 函数原型:
- string& insert(int pos, const char *s);//插入字符串
- string& insert(int pos, const string& str);//插入字符串
- string& insert(int pos, int n, char c);//在指定位置插入n个字符c
- string& erase(int pos, int n = npos);//删除从pos开始的n个字符
- 插入和删除的起始下标都是从0开始
2.1.9 string子串
-
功能描述:
- 从字符串中获取想要的子串
-
函数原型:
- string substr(int pos = 0, int n = npos) const; //返回由pos开始的n个字符组成的字符串
-
代码实现
void test() { string email = "zhangsan@sina.com"; //从邮件地址中 获取 用户名信息 int pos = email.find("@"); cout << pos << endl; string usrName = email.substr(0,pos); cout << usrName << endl; }
2.2 vector容器
2.2.1 vector基本概念
- 功能:
- vector数据结构和数组非常相似,也称为单端数组
- vector与普通数组区别:
- 不同之处在于数组是静态空间,而vector可以动态扩展
- 动态扩展:
- 并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝到新空间,释放原空间
- vector容器的迭代器是支持随机访问的迭代器
2.2.2 vector构造函数
-
功能描述:
- 创建vector容器
-
函数原型:
- vector v; //采用模版实现类实现,默认构造函数
- vector(v.begin(), v.end());//将v[begin(), end())区间中的元素拷贝给本身
- vector(n, elem); //构造函数将n个elem拷贝给本身
- vector(const vector &vec);//拷贝构造函数
-
代码示例
#include <vector> void printVector(vector<int>& v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it <<" "; } cout << endl; } void test01() { vector<int> v1;//无参构造 for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); vector<int> v2(v1.begin(), v1.end()); printVector(v2); vector<int> v3(10, 100); printVector(v3); vector<int> v4(v3); printVector(v4); } int main(){ test01(); system("pause"); return 0; }
2.2.3 vector赋值操作
-
功能描述
- vector& operator=(const vector &vec);//重载等号操作符
- assign(beg, end); //将[beg, end) 区间中的数据拷贝赋值给本身
- assign(n, elem); //将n个elem拷贝赋值给本身
-
代码示例
#include <vector> void printVector(vector<int>& v) { for (vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it <<" "; } cout << endl; } //赋值操作 void test01() { vector<int> v1;//无参构造 for (int i = 0; i < 10; i++) { v1.push_back(i); } printVector(v1); vector<int> v2; v2 = v1; printVector(v2); vector<int> v3; v3.assign(v1.begin(), v1.end()); printVector(v3); vector<int> v4; v4.assign(10, 100); printVector(v4); } int main(){ test01(); system("pause"); return 0; }
2.2.4 vector容量和大小
-
功能描述:
- 对vector容器的容量和大小操作
-
函数原型:
-
empty(); //判断容器是否为空
-
capacity(); //容器的容量
-
size(); //返回容器中元素的个数
-
resize(int num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置
//如果容器变短,则末尾超出容器长度的元素被删除
-
resize(int num, elem); //重新指定容器的长度为num,若容器变长,则以elem填充新位置
//如果容器变短,则末尾超出容器长度的元素被删除
-
2.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(); //删除容器中所有元素
2.2.6 vector数据存取
- 功能描述:
- 对vector中的数据的存取操作
- 函数原型:
- at(int idx); //返回索引idx所指的数据
- operator[]; //返回索引idx所指的数据
- front(); //返回容器中第一个数据元素
- back(); //返回容器中最后一个数据元素
2.2.7 vector互换容器
-
功能描述:
- 实现两个容器内元素进行互换
-
函数原型
- swap(vec); //将vec与本身的元素互换
-
示例代码
#include <vector> void test() { vector<int> v; for(int i = 0; i < 100000; i++){ v.push_back(i); } cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl; v.resize(3);//容量并未发生改变,还是存在内存浪费 cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl; //收缩内存 vector<int>(v).swap(v);//拷贝构造函数创建匿名对象(没有名字),由于前面已经resize,该匿名对象的大小和容量拷贝的的是当前的大小,再和匿名对象互换 容器,容量大小都改为3 cout << "v的容量为:" << v.capacity() << endl; cout << "v的大小为:" << v.size() << endl; }
2.2.8 vector预留空间
-
功能描述:
- 减少vector在动态扩展容量时的扩展次数
-
函数原型:
- reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问
-
实际应用
#include <vector> void test() { vector<int> v; //如果数据量较大,可以一开始就利用reserve预留空间,这样就不需要扩容多次 v.reserve(100000); int num = 0;//统计开辟次数 int *p = NULL; for (int i = 0; i < 100000; i++){ v.push_back(i); if (p != &v[0]){//让指针指向数组起始地址,如果动态扩容了,地址就会改变 p = &v[0]; num++; } } cout << "num:" << num << endl; }
2.3 deque容器
2.3.1 deque容器基本概念
- 功能:
- 双端数组,可以对头端进行插入删除操作
- deque与vector区别:
- vector对于头部的插入删除效率低,数据量越大,效率越低
- deque相对而言,对头部的插入删除速度会比vector快
- vector访问元素时的速度会比deque快,这和两者内部实现有关
- deque内部工作原理
- deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
- 中控器维护的是每个缓冲区的地址,使得使用deque时像一片连续的内存空间
- deque容器的迭代器也是支持随机访问的
2.3.2 deque构造函数
-
功能描述:
- deque容器构造
-
函数原型:
- deque deqT; //默认构造形式
- deque(beg, end); //构造函数将[beg, end) 区间中的元素拷贝给本身
- deque(n, elem); //构造函数将n个elem拷贝给本身
- deque(const deque &deq);//拷贝构造函数
-
代码示例
#include <deque> void printDeque(const deque<int> &d)//只读,相应的迭代器也要加上const { for(deque<int>::const_iterator it = d.begin(); it != d.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { deque<int> d1; for(int i = 0; i < 10; i++) { d1.push_back(i); } printDeque(d1); deque<int> d2(d1.begin(), d1.end()); printDeque(d2); deque<int> d3(10, 100); printDeque(d3); deque<int> d4(d3); printDeque(d4); }
2.3.3 deque赋值操作
- 功能描述:
- 给deque容器进行赋值操作
- 函数原型:
- deque& operator = (const deque &deq); //重载等号操作符
- assign(beg, end); //将[beg, end)区间
- assign(n, elem); //将n个elem拷贝赋值给本身
- deque赋值操作基本与vector相同
2.3.4 deque大小操作
- 功能描述:
- 对deque容器的大小进行操作
- 函数原型:
- deque.empty(); //判断容器是否为空
- deque.size(); //返回容器中元素的个数,deque没有容量这个概念
- deque.resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置,容器变短,则末尾超出容器长度的元素被删除
- deque.resize(num, elem); //如果容器变短,则末尾超出容器长度的元素被删除,若容器变长,则以elem填充新位置
2.3.5 deque 插入和删除
- 功能描述:
- 向deque容器中插入和删除数据
- 函数原型:
- 两端插入操作:
- push_back(elem); //在容器尾部添加一个数据
- push_front(elem); //在容器头部插入一个数据
- pop_back(); //删除容器最后一个数据
- pop_front(); //删除容器第一个数据
- 指定位置操作:(必须提供迭代器iterator)
- insert(pos, elem); //在pos位置插入一个elem元素的拷贝,返回新数据的位置
- insert(pos, n, elem); //在pos位置插入n个elem数据,无返回值
- insert(pos, beg, end) //在pos位置插入[beg,end) 区间的数据(可以是另一个容器的),无返回值
- erase(const_iterator pos); //删除pos位置的数据,返回下一个数据的位置
- erase(const_iterator start, const_iterator end); //删除[beg, end)区间的数据,返回下一个数据的位置
- clear(); //删除容器中所有元素
- 两端插入操作:
2.3.6 deque 数据存取
- 功能描述:
- 对deque 中的数据的存取操作
- 函数原型:
- at(int idx); //返回索引idx所指的数据
- operator[]; //返回索引idx所指的数据
- front(); //返回容器中第一个数据元素
- back(); //返回容器中最后一个数据元素
2.3.7 deque 排序
- 功能描述:
- 利用算法实现对deque容器进行排序
- 算法:
- sort(iterator beg, iterator end) //对beg和end区间内元素进行排序,默认从小到大
- 对于支持随机访问的迭代器的容器,都可以用sort算法排序
2.4 stack容器
2.4.1 stack 基本概念
- stack是一种先进后出的数据结构,它只有一个出口
- 栈只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为
2.4.2 stack常用接口
- 功能描述:
- 栈容器常用的对外接口
- 构造函数:
- stack stk; //stack采用模板类实现,默认构造
- stack(const stack &stk);//拷贝构造函数
- 赋值操作:
- stack& operator=(const stack &stk); //重载等号操作符
- 数据存取:
- push(elem); //向栈顶添加元素
- pop(); //从栈顶移除第一个元素
- top(); //返回栈顶元素
- 大小操作:
- empty(); //判断堆栈是否为空
- size(); //返回栈的大小
2.5 queue容器
2.5.1 queue基本概念
- queue是一种iterator的数据结构,他有两个出口
- 队列容器允许从一端新增元素,从另一端移除元素
- 队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为
- 队列中进数据称为 入队 push
- 队列中出数据称为 出队 pop
2.5.2 queue 常用接口
- 功能描述:队列容器常用的对外接口
- 构造函数:
- queue que; //queue采用模板类实现
- queue(const queue &que); //拷贝构造函数
- 赋值操作:
- queue& operator=(const queue &que); //重载等号操作符
- 数据存取:
- push(elem); //往队尾添加元素
- pop(); //从队头移除第一个元素
- back(); //返回最后一个元素
- front(); //返回第一个元素
- 大小操作:
- empty(); //判断堆栈是否为空
- size(); //返回栈的大小
2.7 list容器
2.7.1 list基本概念
-
链表是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针实现的
-
功能:将数据进行链式存储
-
链表的组成:链表由一系列结点组成
-
结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
-
STL中的链表是一个双向循环链表
-
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移(一次移动一位),属于双向迭代器
-
list的优点:
- 采用动态存储分配,不会造成内存浪费和溢出
- 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
-
list的缺点:
- 链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大
-
List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的
-
STL中的List和vector是两个最常被使用的容器,各有优缺点
2.7.2 list构造函数
-
功能描述:创建list容器
-
函数原型
- list lst; //list采用模板类实现,对象的默认构造形式
- list(beg,end); //构造函数将[beg, end)区间中的元素拷贝给本身
- list(n, elem); //构造函数将n个elem拷贝给本身
- list(const list &lst); //拷贝构造函数
-
代码示例
#include <list> void printList(const list<int>& L){ for(list<int>::const_iterator it = L.begin(); it != L.end(); it++) { cout << *it << " "; } cout << endl; } void test01() { //默认构造 list<int> L1; L1.push_back(10); L1.push_back(20); L1.push_back(30); L1.push_back(40); printList(L1); //区间构造 list<int> L2(L1.begin(), L1.end()); printList(L2); //拷贝构造 list<int> L3(L2); printList(L3); //将n个elem拷贝给本身 list<int> L4(10, 1000); printList(L4); }
-
总结:list构造方式同其他几个STL常用容器,熟练掌握即可
2.7.3 list赋值和交换
- 功能描述:给list容器进行赋值,以及交换list容器
- 函数原型:
- assign(beg, end); //将[beg, end)区间中的数据拷贝赋值给本身
- assign(n, elem); //将n个elem拷贝赋值给本身
- list& operator=(const list &lst); //重载等号操作符
- swap(lst); //将lst与本身的元素互换
2.7.4 list 大小操作
- 功能描述:对list容器的大小进行操作
- 函数原型:
- size(); //返回容器中元素的个数
- empty(); //判断容器是否为空
- resize(num); //重新指定容器的长度为num,若容器变长,则以默认值填充新位置;若容器变短,则末尾超出容器长度的元素被删除
- resize(num, elem); //重新指定容器的长度为num,若容器变长,则以elem填充新位置;若容器变短,则末尾超出容器长度的元素被删除
2.7.5 list 插入和删除
- 功能描述:对list容器进行数据的插入和删除
- 函数原型:
- push_back(elem); //在容器尾部加入一个元素
- pop_back(); //删除容器中最后一个元素
- push_front(elem); //在容器开头插入一个元素
- 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位置的数据,返回下一个数据的位置
- remove(elem); //删除容器中所有与elem值匹配的元素
2.7.6 list 数据存取
-
功能描述:对list容器中数据进行存取
-
函数原型:
-
front(); //返回第一个元素
-
back(); //返回最后一个元素
-
注意:不可以用[] 或 .at()来访问元素,list本质是链表,不是用连续线性空间存储数据,迭代器不支持随机访问
//验证迭代器是不支持随机访问的 list<int>::iterator it = L1.begin(); it++; //支持双向 it--; it = it + 1;//报错,不支持随机访问
-
2.7.7 list 反转和排序
-
功能描述:将容器中的元素反转,以及容器中的数据进行排序
-
函数原型:
-
reverse(); //反转链表
-
sort(); //链表排序
bool myCompare(int val1, int val2) { return val1 > val2; } void test() { list<int> L; L.push_back(10); L.push_back(20); L.push_back(30); L.push_back(40); //反转 L.reverse(); //排序,该排序并非算法当中的排序,而是成员函数 L.sort();//默认规则,从小到大 L.sort(myCompare);//指定规则,从大到小 }
-
-
对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
-
高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂
//案例:将Person自定义数据类型进行排序,规则:按照年龄进行升序,如果年龄相同按照身高进行降序 #include <list> #include <string> class Person{ public: Person(string name, int age, int height) { m_Name = name; m_Age = age; m_Height = height; } public: string m_Name; int m_Age; int m_Height; } bool ComparePerson(Person &p1, Person &p2) { if(p1.m_Age == p2.m_Age) { return p1.m_Height > p2.m_Height;//二次规则 } else { return p1.m_Age < p2.m_Age;//基本规则 } } void test01() { list<Person> L; Person p1("A", 35, 175); Person p2("B", 45, 180); Person p3("C", 40, 170); Person p4("D", 25, 190); Person p5("E", 35, 160); Person p6("F", 35, 200); L.push_back(p1); L.push_back(p2); L.push_back(p3); L.push_back(p4); L.push_back(p5); L.push_back(p6); for(list<Person>::iterator it = L.begin(); it != L.end(); it++){ cout << "姓名:" << it->m_Name << "年龄:" << it->m_Age << "身高:" << it->m_Height << endl; } //指定排序规则 L.sort(ComparePerson); for(list<Person>::iterator it = L.begin(); it != L.end(); it++){ cout << "姓名:" << it->m_Name << "年龄:" << it->m_Age << "身高:" << it->m_Height << endl; } } int main() { test01(); return 0; }
2.8 set / multiset 容器
2.8.1 set基本概念
-
简介:所有元素都会在插入时自动被排序
-
本质:set / multiset 属于关联式容器,底层结构是用二叉树实现
-
set 和 multiset 区别:
- set不允许容器中有重复的元素
- multiset允许容器中有重复的元素
2.8.2 set构造和赋值
-
功能描述:创建set容器以及赋值
-
构造:
- set st; //默认构造函数
- set(const set& st);//拷贝构造函数
-
赋值:
- set& operator=(const set &st); //重载等号操作符
-
代码示例
#include <set> void printSet(const set<int>& s){ for(set<int>::const_iterator it = s.begin(); it != s.end(); it++) { cout << *it << " "; } cout << endl; } void test01{ set<int> s1; //插入数据 只有insert 方式 s1.insert(10); s1.insert(40); s1.insert(30); s1.insert(20); s1.insert(30); printSet(s1); //拷贝构造 set<int> s2(s1); printSet(s2); //赋值 set<int> s3; s3 = s2; printSet(s3); //遍历容器、 //set容器特点:元素都会在插入时自动被排序 //set容器不允许插入重复值,插了不会报错,等于白插 printSet(s1); }
-
总结:
- set容器插入数据时用insert
- set容器插入数据,会在插入时自动排序
2.8.3 set大小和交换
- 功能描述:
- 统计set容器大小以及交换set容器
- 函数原型
- size(); //返回容器中元素的数目
- empty(); //判断容器是否为空
- swap(st); //交换两个集合容器
2.8.4 set插入和删除
- 功能描述:
- set容器进行插入数据和删除数据
- 函数原型:
- insert(elem); //在容器中插入元素
- clear(); //清除所有元素
- erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器
- erase(beg, end); //删除区间[beg,end)的所有元素
- erase(elem); //删除容器中值为elem的元素
2.8.5 set查找和统计
-
功能描述:
- 对set容器进行查找数据以及统计数据
-
函数原型:
- find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
- count(key); //统计key元素的个数
-
代码实现
#include <set> void test01() { set<int> s1; //插入数据 s1.insert(10); s1.insert(30); s1.insert(20); s1.insert(40); set<int>::iterator pos = s1.find(30); if(pos != s1.end()) { cout << "找到元素: " << *pos << endl; } else { cout << "未找到元素" << endl; } } void test02() { set<int> s1; //插入数据 s1.insert(10); s1.insert(30); s1.insert(20); s1.insert(40); //统计个数 int num = s1.count(30); //对于set而言 统计结果 要么是0 要么是1 cout << "num = " << num << endl; }
2.8.6 set和multiset区别
- 学习目标:
- 掌握set和multiset的区别
- 区别:
- set不可以插入重复数据,而multiset可以
- set插入数据的同时会返回插入结果,表示插入是否成功
- multiset不会检测数据,因此可以插入重复数据
2.8.7 pair对组创建
-
功能描述:
- 成对出现的数据,利用对组可以返回两个数据
-
两种创建方式:
- pair<type, type> p(value1, value2);
- pair<type, type> p = make_pair(value1, value2);
-
代码示例
void test01() { //第一种方式 pair<string, int> p("tom", 20); cout << "姓名:" << p.first << "年龄:" << p.second << endl; //第二种方式 pair<string, int> p2 = make_pair("jerry", 30); cout << "姓名:" << p2.first << "年龄:" << p2.second << endl; }
2.8.8 set容器排序
-
学习目标:
- set容器默认排序规则为从小到大,掌握如何改变排序规则
-
主要技术点
-
利用仿函数,可以改变排序规则
-
示例一:set存放内置数据类型
#include <iostream> using namespace std; #include <set> //set容器排序 //仿函数本质上是一个类型,语法规则:返回值是bool类型,重载的符号是小括号就叫仿函数 classs MyCompare { public: bool operator()(int v1, int v2) { return v1 > v2; } }; void test01() { //默认排序从小到大 set<int> s1; s1.insert(10); s1.insert(40); s1.insert(20); s1.insert(50); s1.insert(30); for(set<int>::iterator it = s1.begin(); it != s1.end(); it++) { cout << *it << " "; } cout << endl; //指定排序规则从大到小 set<int, MyCompare> s2; s2.insert(10); s2.insert(40); s2.insert(20); s2.insert(50); s2.insert(30); for(set<int, MyCompare>::iterator it = s1.begin(); it != s1.end(); it++) { cout << *it << " "; } cout << endl; }
-
示例二:set存放自定义数据类型
#include <iostream> using namespace std; #include <set> #include <string> class Person{ public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } public: string m_Name; int m_Age; } classs ComparePerson { public: bool operator()(const Person& p1, const Person& p2) { return p1.m_Age > p2.m_Age; } }; void test01() { //自定义数据类型 都会指定排序规则 set<Person, ComparePerson> s; Person p1("A", 24); Person p2("B", 28); Person p3("C", 25); Person p4("D", 21); s.insert(p1); s.insert(p2); s.insert(p3); s.insert(p4); for(set<Person, ComparePerson>::iterator it = s.begin(); it != s.end(); it++) { cout << "姓名:" << it->m_Name << " 年龄: " << it->m_Age << endl; } }
-
2.9 map/multimap容器
2.9.1 map基本概念
- 简介:
- map中所有元素都是pair
- pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
- 所有元素都会根据元素的键值自动排序
- 本质:
- map/multimap属于关联式容器,底层结构是用二叉树实现
- 优点:
- 可以根据key值快速找到value值
- map/multimap区别:
- map不允许容器中有重复key值元素
- multimap允许容器中有重复key值元素
2.9.2 map构造和赋值
- 功能描述:
- 对map容器进行构造和赋值操作
- 函数原型:
- 构造:
- map<T1, T2> mp; //map默认构造函数
- map(const map &mp); //拷贝构造函数
- 赋值:
- map& operator = (const map &mp);//重载等号操作符
- 构造:
2.9.3 map大小和交换
-
功能描述:
- 统计map容器大小以及交换map容器
-
函数原型:
- size(); //返回容器中元素的数目
- empty(); //判断容器是否为空
- swap(st); //交换两个集合器
-
代码示例
#include <iostream> using namespace std; #include <map> void test01() { map<int, int> m; m.insert(pair<int, int>(1, 10)); m.insert(pair<int, int>(2, 20)); m.insert(pair<int, int>(3, 30)); if (m.empty()) { cout << "m为空" << endl; } else { cout << "m不为空" << endl; cout << "m的大小为:" << m.size() << endl; } } //交换 void test02() { map<int, int> m; m.insert(pair<int, int>(1, 10)); m.insert(pair<int, int>(2, 20)); m.insert(pair<int, int>(3, 30)); map<int, int> m2; m2.insert(pair<int, int>(4, 100)); m2.insert(pair<int, int>(5, 200)); m2.insert(pair<int, int>(6, 300)); m.swap(m2); } int main() { test01(); test02(); return 0; }
2.9.4 map插入和删除
-
功能描述:
- map容器进行插入数据和删除数据
-
函数原型:
- insert(elem); //在容器中插入元素
- clear(); //清除所有元素
- erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器
- erase(beg, end); //删除区间[beg,end)的所有元素,返回下一个元素的迭代器
- erase(key); //删除容器中值为key的元素
-
代码示例
#include <iostream> using namespace std; #include <map> void test01() { //插入 map<int, int> m; //第一种插入方式 m.insert(pair<int,int>(1, 10)); //第二种插入方式 m.insert(make_pair(2, 20)); //第三种插入方式 m.insert(map<int, int>::value_type(3, 30)); //第四种插入方式,对于不存在的key,编译器会把值设为0,不建议用,一般用途是,用key找到value m[4] = 40; }
2.9.5 map查找和统计
- 功能描述
- 对map容器进行查找数据以及统计数据
- 函数原型:
- find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回end();
- count(key); //统计key的元素个数,对于map而言,不是1就是0
2.9.6 map容器排序
-
学习目标
- map容器默认排序规则为从小到大, 按照key值进行从大到小排序,掌握如何改变排序法则
-
主要技术点:
- 利用仿函数,可以改变排序规则
-
代码示例
-
示例一:map存放内置数据类型
#include <iostream> using namespace std; #include <map> //map容器排序 //仿函数本质上是一个类型,语法规则:返回值是bool类型,重载的符号是小括号就叫仿函数 classs MyCompare { public: bool operator()(int v1, int v2) { return v1 > v2; } }; void test01() { //默认排序从小到大 map<int, int, MyCompare> m; m.insert(pair<int, int>(1, 10)); m.insert(pair<int, int>(3, 30)); m.insert(pair<int, int>(2, 20)); for(map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) { cout << "key:" << (*it).first << " value:" << it->second; } }
-
示例二:map存放自定义数据类型
using namespace std; #include <iostream> #include <map> #include <string> class Person{ public: Person(string name, int age) { this->m_Name = name; this->m_Age = age; } public: string m_Name; int m_Age; }; class ComparePerson { public: bool operator()(const Person& p1, const Person& p2) { return p1.m_Age > p2.m_Age; } }; void test01() { //自定义数据类型 必须指定排序规则 map<string, Person, ComparePerson> m; Person p1("A", 24); Person p2("B", 28); Person p3("C", 25); Person p4("D", 21); m.insert(pair<string, Person>(p1.m_Name, p1)); m.insert(pair<string, Person>(p2.m_Name, p2)); m.insert(pair<string, Person>(p3.m_Name, p3)); m.insert(pair<string, Person>(p4.m_Name, p4)); for(map<string, Person, ComparePerson>::iterator it = m.begin(); it != m.end(); it++) { cout << "姓名:" << it->first << " 年龄: " << it->second.m_Age << endl; } }
-
3 STL-函数对象
3.1 函数对象
3.1.1 函数对象概念
概念:
- 重载函数调用操作符的类,其对象称为函数对象
- 函数对象使用重载的()时,行为类似函数调用,也叫仿函数
本质:
函数对象(仿函数)是一个类,不是一个函数
3.1.2 函数对象使用
特点:
-
函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
-
函数对象超出普通函数的概念,函数对象可以有自己的状态
-
函数对象可以作为参数传递
#include <string> //1.函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值 class MyAdd { public: int operator()(int v1, int v2) { return v1 + v2; } }; void test01() { MyAdd myAdd; cout << myAdd(10, 10) << endl; } //2.函数对象可以有自己的状态 class MyPrint { public: MyPrint() { count = 0; } void operator()(string test) { cout << test << endl; count++;//统计使用次数 } int count;//内部自己的状态 }; void test02() { MyPrint myPrint; myPrint("hello world"); myPrint("hello world"); myPrint("hello world"); cout << "myPrint调用次数:" << myPrint.count << endl; } //3.函数对象可以作为参数传递 void doPrint(MyPrint &mp, string test) { mp(test);//调用自己 } void test03() { MyPrint myPrint; doPrint(myPrint, "Hello C++"); } int main() { test01(); test02(); test03(); return 0; }
3.2 谓词
3.2.1 谓词概念
概念:
- 返回bool类型的仿函数称为谓词
- 如果operator()接受一个参数,那么叫做一元谓词
- 如果operator()接受两个参数,那么叫做二元谓词
3.2.2 一元谓词
3.2.3 二元谓词
-
代码示例
#include <vector> #include <algorithm> //二元谓词 class MyCompare { public: bool operator()(int num1, int num2) { return num1 > num2; } }; void test01() { vector<int> v; v.push_back(10); v.push_back(40); v.push_back(20); v.push_back(30); v.push_back(50); //默认从小到大 sort(v.begin(), v.end()); for(vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; cout << "--------------------------------" << endl; //使用函数对象改变算法策略,排序从大到小 sort(v.begin(), v.end(), MyCompare()); for(vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } int main(){ test01(); return 0; }
3.3 内建函数对象
3.3.1 内建函数对象意义
概念:
- STL内建了一些函数对象
分类:
- 算术仿函数
- 关系仿函数
- 逻辑仿函数
用法:
- 这些仿函数所产生的对象,用法和一般函数完全相同
- 使用内建函数对象,需要引入头文件#include
3.3.2 算术仿函数
功能描述:
- 实现四则运算
- 其中negate是一元运算,其它都是二元运算
仿函数原型:
-
template< class T> T plus< 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> //negate void test01() { negate<int> n; cout << n(50) << endl; } //plus void test02() { plus<int> p; cout << p(10, 20) << endl; } int main(){ test01(); test02(); return 0; }
3.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> T bool greater_equal< T > //大于等于
-
template< class T> T bool less< T > //小于
-
template< class T> T bool less_equal< T > //小于等于
-
代码示例
#include <functional> #include <vector> #include <algorithm> void test01() { vector<int> v; v.push_back(10); v.push_back(40); v.push_back(20); v.push_back(30); v.push_back(50); for(vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; //STL内建仿函数 大于仿函数 sort(v.begin(), v.end(), greater<int>()); for(vector<int>::iterator it = v.begin(); it != v.end(); it++) { cout << *it << " "; } cout << endl; } int main(){ test01(); return 0; }
3.3.4 逻辑仿函数
功能描述:
- 实现逻辑运算
函数原型:
- template< class T> bool logical_and< T > //逻辑与
- template< class T> bool logical_or< T > //逻辑非
- template< class T> bool logical_not< T > //逻辑或
4 STL-常用算法
概述:
- 算法主要是由头文件< algorithm > < functional > < numeric >组成
- < algorithm >是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历操作、复制、修改等等
- < numeric >体积很小,只包括几个在序列上面进行简单数学运算的模板函数
- < functional >定义了一些模板类,用以声明函数对象
4.1 常用遍历算法
算法简介:
- for_each //遍历容器
- transform //搬运容器到另一个容器中
4.1.1 for_each
功能描述:
- 实现遍历容器
函数原型:
- for_each(iterator beg, iterator end, _func);
- 遍历算法 遍历容器元素
- beg 开始迭代器
- end 结束迭代器
- _func 函数或者函数对象
4.1.2 transform
功能描述:
- 搬运容器到另一个容器中
函数原型:
-
transform(iterator beg1, iterator end1, iterator beg2, _func);
- beg1 源容器开始迭代器
- end1 源容器结束迭代器
- beg2 目标容器开始迭代器
- _func 函数或者函数对象
-
代码示例
#include <vector> #include <algorithm> //常用遍历算法 搬运 transform class TransForm { public: int operator()(int val) { return val; } }; class MyPrint { public: void operator()(int val) { cout << val << " "; } }; void test01() { vector<int> v; for (int i = 0; i < 10; i++) { v.push_back(i); } vector<int> vTarget;//目标容器 vTarget.resize(v.size());//目标容器需要提前开辟空间 transform(v.begin(), v.end(), vTarget.beigin(), TransForm()); for_each(vTarget.beigin(), vTarget.end(), MyPrint()); } int main(){ test01(); return 0; }
-
总结:搬运的目标容器必须要提前开辟空间,否则无法正常搬运
4.2 常用查找算法
算法简介:
- find //查找元素
- find_if //按条件查找元素
- adjacent_find //查找相邻重复元素
- binary_search //二分查找法
- count //统计元素个数
- count_if //按条件统计元素个数
4.2.1 find
功能描述:
- 查找指定元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()
函数原型:
- find(iterator beg, iterator end, value);
- 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
- beg 开始迭代器
- end 结束迭代器
- value 查找的元素
- 在查找自定义数据类型时,需要重载 == ,否则编译器无法比较
4.2.2 find_if
功能描述:
- 按条件查找元素
函数原型:
- find_if(iterator beg, iterator end, _Pred);
- 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置
- beg开始迭代器
- end结束迭代器
- _pred 函数或者谓词(返回bool类型的仿函数)
4.2.3 adjacent_find
功能描述:
- 查找相邻重复元素
函数原型:
- adjacent_find(iterator beg, iterator end);
- 查找相邻重复元素,返回相邻元素的第一个位置的迭代器
- beg开始迭代器
- end结束迭代器
4.2.4 binary_search
功能描述:
- 查找指定元素是否存在
函数原型:
- bool binary_search(iterator beg, iterator end, value);
- 查找指定的元素,查到返回true 否则 false
- 注意:在无序序列中不可用
- beg开始迭代器
- end结束迭代器
- value查找的元素
4.2.5 count
功能描述:
- 统计元素个数
函数原型:
- count(iterator beg, iterator end, value);
- 统计元素出现次数
- beg开始迭代器
- end结束迭代器
- value统计的元素
- 在统计自定义数据类型时,需要重载 == ,否则编译器无法统计
4.2.6 count_if
功能描述:
- 按条件统计元素个数
函数原型:
- count_if(iterator beg, iterator end, _Pred);
- 按条件统计元素出现次数
- beg开始迭代器
- end结束迭代器
- _Pred 谓词
4.3 常用排序算法
算法简介:
- sort //对容器内元素进行排序
- random_shuffle //洗牌 指定范围内的元素随机调整次序
- merge //容器元素合并,并存储到另一容器中
- reverse //反转指定范围的元素
4.3.1 sort
功能描述:
- 对容器内元素进行排序
函数原型:
- sort(iterator beg, iterator end, _Pred);
- beg 开始迭代器
- end 结束迭代器
- _Pred 谓词
- 两个参数,默认从小到大排序
4.3.2 random_shuffle
功能描述:
- 洗牌 指定范围内的元素随机调整次序
函数原型:
-
random_shuffle(iterator beg, iterator end);
-
指定范围内的元素随机调整次序
-
beg 开始迭代器
-
end 结束迭代器
#include <ctime> //随机种子 srand((unsigned int)time(NULL));
-
4.3.3 merge
功能描述:
- 两个容器元素合并,并存储到另一容器中
函数原型:
- merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
- 容器元素合并,并存储到另一容器中,注意:两个容器必须是有序的
- beg1 容器1开始迭代器
- end1 容器1结束迭代器
- beg2 容器2开始迭代器
- end2 容器2结束迭代器
- dest 目标容器开始迭代器,注意:目标容器需要提前开辟空间
4.3.4 reverse
功能描述:
- 将容器内元素进行反转
函数原型:
- reverse(iterator beg, iterator end);
- 反转指定范围内的元素
- beg 开始迭代器
- end 结束迭代器
4.4 常用拷贝和替换算法
算法简介:
- copy
- replace
- replace_if
- swap
4.4.1 copy
功能描述:
- 两个容器元素合并,并存储到另一容器中
函数原型:
- copy(iterator beg, iterator end, iterator dest);
- beg 开始迭代器
- end 结束迭代器
- dest 目标起始迭代器
4.4.2 replace
功能描述:
- 将容器内指定范围的旧元素修改为新元素
函数原型:
- replace(iterator beg, iterator end, oldvalue, newvalue);
- 将区间内旧元素 替换成 新元素
- beg 开始迭代器
- end 结束迭代器
- oldvalue 旧元素
- newvalue 新元素
4.4.3 replace_if
功能描述:
- 将容器内指定范围的旧元素修改为新元素
函数原型:
- replace_if(iterator beg, iterator end, _pred, newvalue);
- 按条件替换元素,满足条件的替换成指定元素
- beg 开始迭代器
- end 结束迭代器
- _pred 谓词
- newvalue 替换的新元素
4.4.4 swap
功能描述:
- 互换两个容器的元素
函数原型:
- swap(container c1, container c2);
- 互换两个容器(同种类型)的元素
- c1容器1
- c2容器2
4.5 常用算术生成算法
- 算术生成算法属于小型算法,使用时包含的头文件为#include
算法简介:
- accumulate
- fill
4.5.1 accumulate
功能描述:
- 计算区间内 容器元素累计总和
函数原型:
- accumulate(iterator beg, iterator end, value);
- 计算容器元素累计总和
- beg 开始迭代器
- end 结束迭代器
- value 起始累加值
4.5.2 fill
功能描述:
- 向容器中填充指定的元素
函数原型:
- fill(iterator beg, iterator end, value);
- 向容器中填充元素
- beg 开始迭代器
- end 结束迭代器
- value 填充的值
4.6 常用集合算法
算法简介:
- set_intersection
- set_union
- set_difference
4.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 目标容器开始迭代器(开始前需提前开辟空间,两个容器size取小值)
- 返回的是交集后的最后一个元素,可能比目标容器小,输出的时候用返回的迭代器
4.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 目标容器开始迭代器(开始前需提前开辟空间,两个容器相加)
- 返回的是并集后的最后一个元素的位置,可能比目标容器小,输出的时候用返回的迭代器
4.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 目标容器开始迭代器(开始前需提前开辟空间,两个容器size取大值)
- 返回的是差集后的最后一个元素的位置,可能比目标容器小,输出的时候用返回的迭代器