C++-Part3
C++-Part3——提高编程
[TOC]
STL 概述
- 诞生背景
- 长久以来,软件界一直希望建立一种可重复利用的东西
- C++ 的面向对象和泛型编程思想,目的就是复用性的提升
- 大多情况下,数据结构和算法都未能有一套标准,导致被迫从事大量重复工作
- 为了建立数据结构和算法的一套标准,诞生了STL
基本概念
- STL(Standard Template Library,标准模板库)
- STL 从广义上分为:容器(container)、算法(algorithm)、迭代器(iterator)
- 容器和算法之间通过迭代器进行无缝连接。
- STL 几乎所有的代码都采用了模板类或者模板函数
STL 六大组件:
- 容器:各种数据结构,如 vector、list、deque、set、map 等,用来存放数据。
- 算法:各种常用的算法,如 sort、find、copy、for_each 等
- 迭代器:扮演了容器与算法之间的胶合剂。
- 仿函数:行为类似函数,可作为算法的某种策略。
- 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。
- 空间配置器:负责空间的配置与管理。
STL 容器、算法、迭代器
容器:
- STL容器就是将运用最广泛的一些数据结构实现出来
- 常用的数据结构:数组、链表、树、栈、队列、集合、映射表等
- 这些容器分为序列式容器和关联式容器两种:
- 序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置。
- 关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
算法:
- 有限的步骤,解决逻辑或数学上的问题
- 算法分为:质变算法和非质变算法。
- 质变算法:是指运算过程中会更改区间内的元素的内容。例如拷贝、替换、删除等等
- 非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等
迭代器:
提供一种方法,使之能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。
每个容器都有自己专属的迭代器
迭代器使用非常类似于指针
迭代器种类:
种类 功能 支持运算 输入迭代器 对数据的只读访问 只读,支持++、==、!= 输出迭代器 对数据的只写访问 只写,支持++ 前向迭代器 读写操作,并能向前推进迭代器 读写,支持++、==、!= 双向迭代器 读写操作,并能向前和向后操作 读写,支持++、–, 随机访问迭代器 读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器 读写,支持++、–、[n]、-n、<、<=、>、>= 常用的容器中迭代器种类为双向迭代器,和随机访问迭代器
STL 常用容器
string 容器
string 基本概念
本质:
- string 是 C++ 风格的字符串,而 string 本质上是一个类
string 和 char* 区别:
- char* 是一个指针
- string 是一个类,类内部封装了char*,管理这个字符串,是一个 char* 型的容器。
特点:
- string 类内部封装了很多成员方法
- string 管理 char* 所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责
string 构造函数
构造函数原型:
string();
:创建一个空的字符串string(const char* s);
:使用 c 风格字符串初始化string 转 char*:
char*p=(char*)str.data();
或char *p=(char*)str.c_str();
string(const string& str);
:使用一个 string 对象初始化另一个 string 对象string(int n, char c);
:使用 n 个字符 c 初始化
1 | // 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 赋给当前字符串
1 | //赋值 |
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 个字符连接到字符串结尾
1 | //字符串拼接 |
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 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 个字符为字符串 strstring& replace(int pos, int n, const char* s);
:替换从 pos 开始的 n 个字符为字符串 s
- find 找到字符串后返回查找的第一个字符位置,找不到返回 -1
- replace 在替换时,要指定起始位置,替换的目标长度,替换的结果
1 | //查找和替换 |
string 字符串比较
- 比较方式:比较字符的 ASCII 码值(意义不大)
- = 返回 0
- > 返回 1
- < 返回 -1
- 函数原型:
int compare(const string& s) const;
:与字符串 s 比较int compare(const char* s) const;
:与字符串 s 比较
1 | // 字符串比较 |
string 字符存取
string 中单个字符存取方式有两种
char& operator[](int n);
:通过 [] 方式取字符char& at(int n);
:通过 at() 获取字符
可以直接使用增强 for 进行遍历
1 | void test01() { |
string 插入和删除
- 函数原型:
string& insert(int pos, const char* s);
:插入字符串string& insert(int pos, const string& str);
:插入字符串string& insert(int pos, int n, char c);
:在指定位置插入 n 个字符 cstring& erase(int pos, int n = npos);
:删除从 Pos 开始的 n 个字符
- 注意:插入和删除的起始下标都是从 0 开始
1 | //字符串插入和删除 |
string 子串
- 函数原型:
string substr(int pos = 0, int n = npos) const;
:返回由 pos 开始的 n 个字符组成的字符串
- 总结:灵活的运用求子串功能,可以在实际开发中获取有效的信息
1 | //子串 |
string 大小
size()
:获得字符串的长度capacity()
:获得该字符串的总空间大小
vector 容器
vector 基本概念
功能:
- vector 数据结构和数组非常相似,也称为单端数组
vector 与普通数组区别:
- 不同之处在于数组是静态空间,而 vector 封装了动态扩展
动态扩展:
- 并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
vector 容器的迭代器是支持随机访问的迭代器
vector 构造函数
- 函数原型:
vector<T> v;
:采用模板实现类实现,默认构造函数vector(v.begin(), v.end());
:将 [begin(), end()) 区间中的元素拷贝给本身。vector(n, elem);
:构造函数将 n 个 elem 拷贝给本身。vector(const vector &vec);
:拷贝构造函数。
1 | void printVector(vector<int> &v) { |
vector 赋值操作
函数原型:
vector& operator=(const vector &vec);
:重载等号操作符assign(beg, end);
:将[beg, end)区间中的数据拷贝赋值给本身。assign(n, elem);
:将n个elem拷贝赋值给本身。
1 | // 赋值操作 |
vector 容量和大小
- 函数原型:
empty();
:判断容器是否为空capacity();
:返回容器的容量size();
:返回容器中元素的个数resize(int num, elem);
:重新指定容器的长度为 num- 若容器变长,则以 elem 填充新位置。若没有提供 elem,则填充默认值 0。
- 如果容器变短,则末尾超出容器长度的元素被删除。
1 | void test01() { |
vector 插入和删除
- 函数原型:
push_back(ele);
:尾部插入元素 elepop_back();
:删除最后一个元素insert(const_iterator pos, ele);
:迭代器指向位置 pos 插入元素 eleinsert(const_iterator pos, int count,ele);
:迭代器指向位置 pos 插入 count 个元素 eleerase(const_iterator pos);
:删除迭代器指向的元素erase(const_iterator start, const_iterator end);
:删除迭代器从 start 到 end 之间的元素clear();
:删除容器中所有元素
1 | //插入和删除 |
vector 数据存取
函数原型:
at(int idx);
:返回索引 idx 所指的数据operator[];
:返回索引 idx 所指的数据front();
:返回容器中第一个数据元素back();
:返回容器中最后一个数据元素
建议直接使用增强 for
1
2
3
4
5
6void printVector(vector<int> &v) {
for (int &it : v) {
cout << it << " ";
}
cout << endl;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23void test01() {
vector<int> v1;
for (int i = 0; i < 10; i++) {
v1.push_back(i);
}
for (int i = 0; i < v1.size(); i++) {
cout << v1[i] << " ";
}
cout << endl;
for (int i = 0; i < v1.size(); i++) {
cout << v1.at(i) << " ";
}
cout << endl;
cout << "v1的第一个元素为: " << v1.front() << endl;
cout << "v1的最后一个元素为: " << v1.back() << endl;
}
int main() {
test01();
return 0;
}vector 互换容器
函数原型:
swap(vec);
:将 vec 与本身的元素互换
总结:swap 可以使两个容器互换,可以达到实用的收缩内存效果(因为使用的当前容器的 size 来初始化了匿名对象)
1 | void test01() { |
vector 预留空间
函数原型:
reserve(int len);
:容器预留 len 个元素长度,预留位置不初始化,元素不可访问。
总结:如果数据量较大,可以一开始利用 reserve 预留空间,以免添加数据时不断复制扩张
1 | void test01() { |
deque 容器
deque 容器基本概念
功能:
- 双端数组,可以对头端进行插入删除操作
deque 与 vector 区别:
- vector 对于头部的插入删除效率低,数据量越大,效率越低
- deque 相对而言,对头部的插入删除速度回比 vector 快
- vector 访问元素时的速度会比 deque 快
- deque 内部工作原理:
- deque 内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
- 中控器维护的是每个缓冲区的地址,使得使用 deque 时像一片连续的内存空间
- deque 容器的迭代器也是支持随机访问的
deque 构造函数
- 函数原型:
deque<T> deqT;
:默认构造形式deque(beg, end);
:构造函数将 [beg, end) 区间中的元素拷贝给本身。deque(n, elem);
:构造函数将 n 个 elem 拷贝给本身。deque(const deque &deq);
:拷贝构造函数
1 |
|
deque 赋值操作
函数原型:
deque& operator=(const deque& deq);
:重载等号操作符assign(beg, end);
:将 [beg, end) 区间中的数据拷贝赋值给本身。assign(n, elem);
:将 n 个 elem 拷贝赋值给本身。
1 | // 赋值操作 |
deque 大小操作
函数原型:
deque.empty();
:判断容器是否为空deque.size();
:返回容器中元素的个数deque.resize(num, elem);
:重新指定容器的长度为 num,若容器变长,若容器变长,则以 elem 值填充新位置。若没有提供 elem,则以默认值填充新位置。
- 如果容器变短,则末尾超出容器长度的元素被删除。
deque 没有容量的概念
1 | // 大小操作 |
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 位置的数据,返回下一个数据的位置。
插入和删除提供的位置是迭代器
1 | //两端操作 |
deque 数据存取
函数原型:
at(int idx);
:返回索引 idx 所指的数据operator[];
:返回索引 idx 所指的数据front();
:返回容器中第一个数据元素back();
:返回容器中最后一个数据元素
可以直接使用增强 for
1 | //数据存取 |
deque 排序
- 算法:
sort(iterator beg, iterator end)
:对 beg 和 end 区间内元素进行排序
- 使用时包含头文件 algorithm
1 |
|
stack 容器
stack 基本概念
概念:stack 是一种先进后出(First In Last Out, FILO)的数据结构,它只有一个出口
栈中只有顶端的元素才可以被外界使用,因此栈不允许有遍历行为
stack 常用接口
构造函数:
stack<T> stk;
:stack 采用模板类实现,stack 对象的默认构造形式stack(const stack &stk);
:拷贝构造函数
赋值操作:
stack& operator=(const stack &stk);
:重载等号操作符
数据存取:
push(elem);
:向栈顶添加元素pop();
:从栈顶移除第一个元素top();
:返回栈顶元素
大小操作:
empty();
:判断堆栈是否为空size();
:返回栈的大小
1 |
|
queue 容器
queue 基本概念
概念:Queue 是一种先进先出(First In First Out, FIFO)的数据结构,它有两个出口
队列容器允许从一端新增元素,从另一端移除元素
队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为
queue 常用接口
构造函数:
queue<T> que;
:queue 采用模板类实现,queue 对象的默认构造形式queue(const queue &que);
:拷贝构造函数
赋值操作:
queue& operator=(const queue &que);
:重载等号操作符
数据存取:
push(elem);
:往队尾添加元素pop();
:从队头移除第一个元素back();
:返回最后一个元素front();
:返回第一个元素
大小操作:
empty();
:判断堆栈是否为空size();
:返回栈的大小
1 |
|
list容器
list 基本概念
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
- 链表的组成:链表由一系列结点组成
- 结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
STL 中的链表是一个双向循环链表
由于链表的存储方式并不是连续的内存空间,因此链表 list 中的迭代器只支持前移和后移,属于双向迭代器
list 的优点:
- 采用动态存储分配,不会造成内存浪费和溢出
- 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
list 的缺点:
- 链表灵活,但是空间(指针域)和 时间(遍历)额外耗费较大
List 有一个重要的性质,插入操作和删除操作都不会造成原有 list 迭代器的失效,这在 vector 是不成立的。
总结:STL 中 List 和 vector 是两个最常被使用的容器,各有优缺点
list 构造函数
- 函数原型:
list<T> lst;
:list采用采用模板类实现,对象的默认构造形式:list(beg,end);
:构造函数将[beg, end)区间中的元素拷贝给本身。list(n,elem);
:构造函数将n个elem拷贝给本身。list(const list &lst);
:拷贝构造函数。
1 |
|
list 赋值和交换
- 函数原型:
assign(beg, end);
:将 [beg, end) 区间中的数据拷贝赋值给本身。assign(n, elem);
:将 n 个 elem 拷贝赋值给本身。list& operator=(const list &lst);
:重载等号操作符swap(lst);
:将lst与本身的元素互换。
1 | // 赋值 |
list 大小操作
函数原型:
size();
:返回容器中元素的个数empty();
:判断容器是否为空resize(num);
:重新指定容器的长度为 num- 若容器变长,则以 elem 值填充新位置。若没有提供 elem,则以默认值填充新位置。
- 若容器变短,则末尾超出容器长度的元素被删除。
1 | //大小操作 |
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 值匹配的元素。
- 插入和删除提供的位置是迭代器
1 | //插入和删除 |
list 数据存取
- 函数原型:
front();
:返回第一个元素。back();
:返回最后一个元素。
1 | // 数据存取 |
list 反转和排序
- 函数原型:
reverse();
:反转链表sort();
:链表排序
1 | bool myCompare(int val1, int val2) { |
set/multiset 容器
set 基本概念
简介:
- 所有元素都会在插入时自动被排序
本质:
- set/multiset 属于关联式容器,底层结构是用二叉树实现。
set 和 multiset 区别:
- set 不允许容器中有重复的元素
- multiset 允许容器中有重复的元素
set 构造和赋值
构造:
set<T> st;
:默认构造函数:set(const set &st);
:拷贝构造函数
赋值:
set& operator=(const set &st);
:重载等号操作符
1 |
|
set 大小和交换
- 函数原型:
size();
:返回容器中元素的数目empty();
:判断容器是否为空swap(st);
:交换两个集合容器
1 | // 大小 |
set 插入和删除
- 函数原型:
insert(elem);
:在容器中插入元素。clear();
:清除所有元素erase(pos);
:删除 pos 迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
:删除区间 [beg,end) 的所有元素 ,返回下一个元素的迭代器。erase(elem);
:删除容器中值为 elem 的元素。
1 | // 插入和删除 |
set 查找和统计
- 函数原型:
find(key);
:查找 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
。count(key);
:统计 key 的元素个数(对于set,结果为 0 或者 1)
1 | // 查找和统计 |
set 和 multiset 区别
- 区别:
- set 不可以插入重复数据,而 multiset 可以插入重复数据
- set 插入数据会返回迭代器与结果的对组
pair<set<int>::iterator, bool>
,取.second
表示插入是否成功 - multiset 插入数据时,仅返回插入结果的迭代器
1 | // set和multiset区别 |
pair 对组创建
- 两种创建方式:
pair<type, type> p ( value1, value2 );
pair<type, type> p = make_pair( value1, value2 );
1 | // 对组创建 |
set 容器排序
- 总结:
- 只能使用仿函数指定 set 容器的排序规则,不能传递普通函数
- 仿函数必须用 const 修饰为常函数
- 对于自定义数据类型,set 必须指定排序规则才可以插入数据
1 | class Person { |
map/multimap 容器
map 基本概念
简介:
- map 中所有元素都是 pair
- pair 中第一个元素为 key(键值),第二个元素为 value(实值)
- 所有元素都会根据元素的键值自动排序
本质:
- map/multimap 属于关联式容器,底层结构是用二叉树实现。
优点:
- 可以根据 key 值快速找到 value 值
map 和 multimap 区别:
- map 不允许容器中有重复 key 值元素
- multimap 允许容器中有重复 key 值元素
map 构造和赋值
函数原型:
构造:
map<T1, T2> mp;
:map 默认构造函数:map(const map &mp);
:拷贝构造函数
赋值:
map& operator=(const map &mp);
:重载等号操作符
总结:map 中所有元素都是成对出现,插入数据时候要使用对组
1 |
|
map 大小和交换
- 函数原型:
size();
:返回容器中元素的数目empty();
:判断容器是否为空swap(st);
:交换两个集合容器
1 | void test01() { |
map 插入和删除
函数原型:
insert(elem);
:在容器中插入元素。clear();
:清除所有元素erase(pos);
:删除 pos 迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
:删除区间 [beg,end) 的所有元素 ,返回下一个元素的迭代器。erase(key);
:删除容器中值为 key 的元素。
提供的 pos 可以为迭代器或者直接为 key
中括号重载调用,在数据不存在的情况下,会直接初始化一个 0 值,因此不推荐读取时使用。
1 | void test01() { |
map 查找和统计
- 函数原型:
find(key);
:查找 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
。count(key);
:统计 key 的元素个数(对于 map,结果为 0 或者 1)
1 | // 查找和统计 |
map 容器排序
总结:
- 只能使用仿函数指定 map 容器的排序规则,不能传递普通函数
- 仿函数必须用 const 修饰为常函数
- 对于自定义数据类型,map 必须指定排序规则才可以插入数据
1 | class MyCompare { |
STL 函数对象
函数对象
函数对象概念
概念:
- 重载函数调用操作符的类,其对象常称为函数对象
- 函数对象使用重载的
()
时,行为类似函数调用,也叫仿函数
本质:
- 函数对象(仿函数)是一个类,不是一个函数
函数对象使用
- 特点:
- 函数对象在使用时,可以像普通函数那样调用,可以有参数,可以有返回值
- 函数对象超出普通函数的概念,函数对象可以有自己的状态
- 函数对象可以作为参数传递
1 | // 1. 函数对象在使用时,可以像普通函数那样调用, 可以有参数,可以有返回值 |
谓词
谓词概念
概念:
- 返回 bool 类型的仿函数称为谓词
- 一元谓词:operator() 接受一个参数
- 二元谓词:operator() 接受两个参数
此处与之前不同,可以传递 struct、class、普通函数。
一元谓词
1 | // 1. 一元谓词 |
二元谓词
1 |
|
内建函数对象
内建函数对象意义
概念:
- STL 内建的一些函数对象
分类:
算术仿函数
关系仿函数
逻辑仿函数
使用内建函数对象,需要引入头文件
#include<functional>
算术仿函数
- 仿函数原型:
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>
:取反仿函数
1 |
|
关系仿函数
- 仿函数原型:
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>
:小于等于
1 |
|
逻辑仿函数
- 函数原型:
template<class T> bool logical_and<T>
:逻辑与template<class T> bool logical_or<T>
:逻辑或template<class T> bool logical_not<T>
:逻辑非
1 |
|
STL 常用算法
- 概述:
- 算法主要是由头文件
<algorithm>
<functional>
<numeric>
组成。
- 算法主要是由头文件
<algorithm>
:是所有 STL 头文件中最大的一个,范围涉及到比较、 交换、查找、遍历操作、复制、修改等<numeric>
:体积很小,只包括几个在序列上面进行简单数学运算的模板函数<functional>
:定义了一些模板类,用以声明函数对象。
常用遍历算法
- 算法简介:
for_each
:遍历容器(常用)transform
:搬运容器到另一个容器中
for_each
- 函数原型:
for_each(iterator beg, iterator end, _func);
:遍历算法 遍历容器元素- beg 开始迭代器
- end 结束迭代器
- _func 函数或者函数对象
1 |
|
transform
函数原型:
transform(iterator beg1, iterator end1, iterator beg2, _func);
- beg1:源容器开始迭代器
- end1:源容器结束迭代器
- beg2:目标容器开始迭代器
- _func:函数或者函数对象
注意:搬运的目标容器必须要提前开辟空间,否则无法正常搬运
1 |
|
常用查找算法
- 算法简介:
find
:查找元素find_if
:按条件查找元素adjacent_find
:查找相邻重复元素binary_search
:二分查找法count
:统计元素个数count_if
:按条件统计元素个数
find
- 函数原型:
find(iterator beg, iterator end, value);
:按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置- beg:开始迭代器
- end:结束迭代器
- value:查找的元素
1 |
|
find_if
- 函数原型:
find_if(iterator beg, iterator end, _Pred);
:按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置- beg:开始迭代器
- end:结束迭代器
- _Pred:函数或者谓词(返回bool类型的仿函数)
1 |
|
adjacent_find
- 函数原型:
adjacent_find(iterator beg, iterator end);
:查找相邻重复元素,返回相邻元素的第一个位置的迭代器- beg:开始迭代器
- end:结束迭代器
1 |
|
binary_search
- 函数原型:
bool binary_search(iterator beg, iterator end, value);
:查找指定的元素,查到则返回 true,否则 false。- beg:开始迭代器
- end:结束迭代器
- value:查找的元素
- 注意:在无序序列中不可用
1 |
|
count
- 函数原型:
count(iterator beg, iterator end, value);
:统计元素出现次数- beg:开始迭代器
- end:结束迭代器
- value:统计的元素
- 统计自定义数据类型时候,需要配合重载
operator==
。
1 |
|
count_if
- 函数原型:
count_if(iterator beg, iterator end, _Pred);
:按条件统计元素出现次数- beg:开始迭代器
- end:结束迭代器
- _Pred:谓词
1 |
|
常用排序算法
- 算法简介:
sort
:对容器内元素进行排序random_shuffle
:洗牌 指定范围内的元素随机调整次序merge
:容器元素合并,并存储到另一容器中reverse
:反转指定范围的元素
sort
- 函数原型:
sort(iterator beg, iterator end, _Pred);
:按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置- beg:开始迭代器
- end:结束迭代器
- _Pred:谓词
1 |
|
random_shuffle
- 函数原型:
random_shuffle(iterator beg, iterator end);
:指定范围内的元素随机调整次序- beg:开始迭代器
- end:结束迭代器、
random_shuffle
在 C++11 中被标记 deprecated,在 C++14 中被 removed。
1 |
|
merge
- 函数原型:
merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
:容器元素合并,并存储到另一容器中- beg1:容器 1 开始迭代器
- end1:容器 1 结束迭代器
- beg2:容器 2 开始迭代器
- end2:容器 2 结束迭代器
- dest:目标容器开始迭代器
- 注意: 两个容器必须是有序的
1 | class myPrint { |
reverse
- 函数原型:
reverse(iterator beg, iterator end);
:反转指定范围的元素- beg:开始迭代器
- end:结束迭代器
1 |
|
常用拷贝和替换算法
- 算法简介:
copy
:容器内指定范围的元素拷贝到另一容器中replace
:将容器内指定范围的旧元素修改为新元素replace_if
:容器内指定范围满足条件的元素替换为新元素swap
:互换两个容器的元素
copy
- 函数原型:
copy(iterator beg, iterator end, iterator dest);
:按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置- beg:源开始迭代器
- end:源结束迭代器
- dest:目标起始迭代器
- 拷贝前需要提前开辟空间
1 |
|
replace
- 函数原型:
replace(iterator beg, iterator end, oldvalue, newvalue);
:将区间内旧元素替换成新元素- beg:开始迭代器
- end:结束迭代器
- oldvalue:旧元素
- newvalue:新元素
1 |
|
replace_if
- 函数原型:
replace_if(iterator beg, iterator end, _pred, newvalue);
:按条件替换元素,满足条件的替换成指定元素- beg:开始迭代器
- end:结束迭代器
- _pred:谓词
- newvalue:替换的新元素
1 |
|
swap
- 函数原型:
swap(container c1, container c2);
:互换两个容器的元素- c1:容器1
- c2:容器2
- swap 交换容器时,注意交换的容器要同种类型
1 |
|
常用算术生成算法
注意:
- 算术生成算法属于小型算法,使用时包含的头文件为
#include <numeric>
- 通常比较实用
- 算术生成算法属于小型算法,使用时包含的头文件为
算法简介:
accumulate
:计算容器元素累计总和fill
:向容器中添加元素
accumulate
- 函数原型:
accumulate(iterator beg, iterator end, value);
:计算容器元素累计总和- beg:开始迭代器
- end:结束迭代器
- value:起始值
1 |
|
fill
- 函数原型:
fill(iterator beg, iterator end, value);
:向容器中填充元素- beg:开始迭代器
- end:结束迭代器
- value:填充的值
1 |
|
常用集合算法
算法简介:
set_intersection
:求两个容器的交集set_union
:求两个容器的并集set_difference
:求两个容器的差集
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 返回值是交集中最后一个元素的位置。
1 |
|
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 返回值既是并集中最后一个元素的位置。
1 |
|
set_difference
- 函数原型:
set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
:求两个集合的差集- beg1:容器 1 开始迭代器
- end1:容器 1 结束迭代器
- beg2:容器 2 开始迭代器
- end2:容器 2 结束迭代器
- dest:目标容器开始迭代器
- 注意:
- v1 和 v2 的差集与 v2 和 v1 的差集是不一样的。
- 求差集的两个集合必须是有序序列。
- 目标容器开辟空间需要从两个容器取较大值。
- set_difference 返回值既是差集中最后一个元素的位置。
1 |
|