STL
- 定义
- STL六大组件
- 容器——置物之所也
- STL容器就是将运用最广泛的一些数据结构实现出来
- 常用的数据结构
- 序列式容器
- 关联式容器
- 算法——问题之解法也
- 质变算法
- 非质变算法
- 迭代器——容器和算法之间粘合剂
- 迭代器种类
- 各种迭代器支持的常见运算操作
- STL示例
- 容器 —— `vector`
- 迭代器: `vector<int>::iterator`
- 算法—— `for_each`
- 示例
- 常用的算法函数
- 排序算法:
- 查找算法:
- 合并算法:
定义
STL是C++中的一个重要组成部分。它的设计理念是提供一套通用、高效、可重用的数据结构和算法,并且尽量通过模板来实现泛化,以便满足各种不同的需求。
STL 从广义上分为: 容器(container) ,算法(algorithm) ,迭代器(iterator)
容器是用来存储数据的对象,可以看作是某种特定数据结构的封装。STL提供了多种不同类型的容器,如vector、list、map等,每种容器都有自己的特点和适用场景。
算法是对容器中数据进行操作的函数,比如查找、排序、删除等。STL提供了大量的算法,包括查找、排序、统计、遍历等等,可以方便地对容器中的元素进行各种处理。
迭代器是用于遍历容器中元素的对象,可以看作是一个指针。通过迭代器,可以按照线性顺序访问容器中的每个元素,从而实现对容器的操作。
STL的关键之处在于容器和算法之间通过迭代器进行无缝连接。算法并不依赖于具体的容器类型,而是通过迭代器来遍历和操作容器中的元素。这种设计使得算法可以复用于多种不同类型的容器,提高了代码的可重用性和灵活性。
STL的很多代码都采用了模板类或者模板函数的形式,这是为了实现泛化编程,即可以对不同的数据类型都适用。通过使用模板,STL可以根据不同的参数类型生成相应的代码,从而实现通用性和灵活性。
STL六大组件
STL大体分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器
- 容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据。
- 算法:各种常用的算法,如sort、find、copy、for_each等
- 迭代器:扮演了容器与算法之间的胶合剂。
- 仿函数:行为类似函数,可作为算法的某种策略。
- 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。
- 空间配置器:负责空间的配置与管理。
容器——置物之所也
STL容器就是将运用最广泛的一些数据结构实现出来
容器(Containers)用于存储和组织数据,并提供了对数据的访问和操作。常见的容器有vector、list、deque、set、map等。
常用的数据结构
数组, 链表,树, 栈, 队列, 集合, 映射表 等
这些容器分为序列式容器和关联式容器两种
序列式容器
强调值的排序,序列式容器中的每个元素均有固定的位置
关联式容器
二叉树结构,各元素之间没有严格的物理上的顺序关系
算法——问题之解法也
有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms)
算法是对容器中的数据进行处理和操作的函数模板。STL提供了一系列算法,涵盖了各种常见的操作,如排序、查找、合并、复制等。
算法分为:质变算法和非质变算法。
质变算法
是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等
非质变算法
是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等
迭代器——容器和算法之间粘合剂
迭代器(Iterators)用于遍历容器中的元素。它提供了一种统一的访问容器中元素的方式,使得算法能够独立于容器而工作,能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。
每个容器都有自己专属的迭代器
迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针
常用的容器中迭代器种类为双向迭代器,和随机访问迭代器
迭代器种类
种类 | 功能 | 支持运算 |
---|---|---|
输入迭代器 | 对数据的只读访问 | 只读,支持++、==、!= |
输出迭代器 | 对数据的只写访问 | 只写,支持++ |
前向迭代器 | 读写操作,并能向前推进迭代器 | 读写,支持++、==、!= |
双向迭代器 | 读写操作,并能向前和向后操作 | 读写,支持++、–, |
随机访问迭代器 | 读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器 | 读写,支持++、–、[n]、-n、<、<=、>、>= |
- 输入迭代器(Input Iterator):这种迭代器只能用于读取数据,它允许以顺序方式逐个访问元素,但不支持对元素进行写操作。例如,
std::istream_iterator
是一个输入迭代器,用于从输入流中读取数据。 - 输出迭代器(Output Iterator):这种迭代器只能用于写入数据,它允许以顺序方式逐个写入元素,但不支持读取元素。例如,
std::ostream_iterator
是一个输出迭代器,用于向输出流中写入数据。 - 前向迭代器(Forward Iterator):这种迭代器支持输入和输出操作,可以在集合中前后移动,并对元素进行读写操作,但只能遍历集合一次。例如,
std::forward_list
和std::unordered_set
的迭代器就属于前向迭代器。 - 双向迭代器(Bidirectional Iterator):这种迭代器比前向迭代器更强大,除了支持前向和后向移动外,还可以反向遍历集合。例如,
std::list
和std::set
的迭代器就属于双向迭代器。 - 随机访问迭代器(Random Access Iterator):这种迭代器提供了最强大的功能,除了支持前向、后向和随机移动外,还可以通过迭代器进行算术计算,实现跳跃式访问集合中的元素。例如,
std::vector
和std::array
的迭代器就属于随机访问迭代器。
不同类型的迭代器支持的运算操作也略有不同。
各种迭代器支持的常见运算操作
- 输入迭代器(Input Iterator):支持以下操作:
*it
:获取迭代器指向的元素值。it++
或++it
:将迭代器向前移动到下一个位置。it == it2
和it != it2
:比较两个迭代器是否相等或不相等。
- 输出迭代器(Output Iterator):支持以下操作:
*it = value
:将值赋给迭代器指向的位置。it++
或++it
:将迭代器向前移动到下一个位置。
- 前向迭代器(Forward Iterator):除了支持输入迭代器和输出迭代器的所有操作之外,还支持以下操作:
it1 == it2
和it1 != it2
:比较两个迭代器是否相等或不相等。
- 双向迭代器(Bidirectional Iterator):除了支持前向迭代器的所有操作之外,还支持以下操作:
it--
或--it
:将迭代器向后移动到前一个位置。
- 随机访问迭代器(Random Access Iterator):除了支持双向迭代器的所有操作之外,还支持以下操作:
it += n
和it -= n
:将迭代器向前或向后移动 n 个位置。it + n
和it - n
:返回从迭代器开始向前或向后移动 n 个位置后的迭代器。it1 - it2
:计算两个迭代器之间的距离。it[n]
:返回迭代器指向的位置加上 n 的元素。
STL示例
容器 —— vector
创建vector容器对象,并且通过模板参数指定容器中存放的数据的类型:
vector<int> v;
迭代器: vector<int>::iterator
(每一个容器都有自己的迭代器,迭代器是用来遍历容器中的元素)
v.begin()
返回迭代器,这个迭代器指向容器中第一个数据
v.end()
返回迭代器,这个迭代器指向容器元素的最后一个元素的下一个位置
vector<int>::iterator
拿到vector这种容器的迭代器类型
vector<int>::iterator it
创建迭代器对象
算法—— for_each
使用STL提供标准遍历算法 头文件 algorith
for_each
是C++算法库中的一个函数,用于对容器或范围内的元素逐个进行某种操作(函数)。
函数原型如下:
template<class InputIt, class UnaryFunction>
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);
参数说明:
first
和last
:表示一个范围,指定需要进行操作的元素的起始和结束位置。f
:是一个一元函数对象(unary function),用于对元素进行操作。该函数对象接受一个元素作为参数,并返回结果(可选)。
for_each
函数会遍历指定范围内的每一个元素,将每个元素传递给函数对象 f
进行处理。
示例
#include <vector>
#include <algorithm>void MyPrint(int val)
{cout << val << endl;
}void 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;}cout << endl;//第三种遍历方式://使用STL提供标准遍历算法 头文件 algorithmfor_each(v.begin(), v.end(), MyPrint);
}int main() {test01();system("pause");return 0;
}
常用的算法函数
#include <algorithm>
是 C++ 中用于包含算法库的头文件。该头文件中包含了许多有用的算法函数,可以对容器、数组和其他数据结构进行各种操作,例如排序、查找、合并等。
使用 #include <algorithm>
可以使程序能够使用算法库中的函数。你可以根据需要选择适当的算法函数来处理数据,提高编程效率和代码可读性。
排序算法:
std::sort(first, last)
:对指定范围内的元素进行升序排序。std::stable_sort(first, last)
:对指定范围内的元素进行稳定的升序排序。
查找算法:
std::find(first, last, value)
:在指定范围内查找第一个与给定值相等的元素,并返回其迭代器。std::binary_search(first, last, value)
:在已排序的范围内使用二分查找算法查找指定值,返回是否找到。
合并算法:
std::merge(first1, last1, first2, last2, result)
:将两个已排序的范围归并成一个有序范围。