Day 21 C ++ STL(Standard Template Library,标准模板库)

STL

  • 定义
  • STL六大组件
      • 容器——置物之所也
          • STL容器就是将运用最广泛的一些数据结构实现出来
          • 常用的数据结构
          • 序列式容器
          • 关联式容器
      • 算法——问题之解法也
          • 质变算法
          • 非质变算法
      • 迭代器——容器和算法之间粘合剂
          • 迭代器种类
          • 各种迭代器支持的常见运算操作
  • STL示例
      • 容器 —— `vector`
      • 迭代器: `vector::iterator`
      • 算法—— `for_each`
      • 示例
      • 常用的算法函数
          • 排序算法:
          • 查找算法:
          • 合并算法:

定义

STL是C++中的一个重要组成部分。它的设计理念是提供一套通用、高效、可重用的数据结构和算法,并且尽量通过模板来实现泛化,以便满足各种不同的需求。

STL 从广义上分为: 容器(container) ,算法(algorithm) ,迭代器(iterator)

容器是用来存储数据的对象,可以看作是某种特定数据结构的封装。STL提供了多种不同类型的容器,如vector、list、map等,每种容器都有自己的特点和适用场景。

算法是对容器中数据进行操作的函数,比如查找、排序、删除等。STL提供了大量的算法,包括查找、排序、统计、遍历等等,可以方便地对容器中的元素进行各种处理。

迭代器是用于遍历容器中元素的对象,可以看作是一个指针。通过迭代器,可以按照线性顺序访问容器中的每个元素,从而实现对容器的操作。

STL的关键之处在于容器和算法之间通过迭代器进行无缝连接。算法并不依赖于具体的容器类型,而是通过迭代器来遍历和操作容器中的元素。这种设计使得算法可以复用于多种不同类型的容器,提高了代码的可重用性和灵活性。

STL的很多代码都采用了模板类或者模板函数的形式,这是为了实现泛化编程,即可以对不同的数据类型都适用。通过使用模板,STL可以根据不同的参数类型生成相应的代码,从而实现通用性和灵活性。

STL六大组件

STL大体分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

  1. 容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据。
  2. 算法:各种常用的算法,如sort、find、copy、for_each等
  3. 迭代器:扮演了容器与算法之间的胶合剂。
  4. 仿函数行为类似函数,可作为算法的某种策略。
  5. 适配器:一种用来修饰容器或者仿函数或迭代器接口的东西。
  6. 空间配置器:负责空间的配置与管理。

容器——置物之所也

STL容器就是将运用最广泛的一些数据结构实现出来

容器(Containers)用于存储和组织数据,并提供了对数据的访问和操作。常见的容器有vector、list、deque、set、map等。

常用的数据结构

数组, 链表,树, 栈, 队列, 集合, 映射表 等

这些容器分为序列式容器关联式容器两种

序列式容器

强调值的排序,序列式容器中的每个元素均有固定的位置

关联式容器

二叉树结构,各元素之间没有严格的物理上的顺序关系

算法——问题之解法也

有限的步骤,解决逻辑或数学上的问题,这一门学科我们叫做算法(Algorithms)
算法是对容器中的数据进行处理和操作的函数模板。STL提供了一系列算法,涵盖了各种常见的操作,如排序、查找、合并、复制等。

算法分为:质变算法非质变算法

质变算法

是指运算过程中会更改区间内的元素的内容。例如拷贝,替换,删除等等

非质变算法

是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等

迭代器——容器和算法之间粘合剂

迭代器(Iterators)用于遍历容器中的元素。它提供了一种统一的访问容器中元素的方式,使得算法能够独立于容器而工作,能够依序寻访某个容器所含的各个元素,而又无需暴露该容器的内部表示方式。

每个容器都有自己专属的迭代器

迭代器使用非常类似于指针,初学阶段我们可以先理解迭代器为指针

常用的容器中迭代器种类为双向迭代器,和随机访问迭代器

迭代器种类
种类 功能 支持运算
输入迭代器 对数据的只读访问 只读,支持++、==、!=
输出迭代器 对数据的只写访问 只写,支持++
前向迭代器 读写操作,并能向前推进迭代器 读写,支持++、==、!=
双向迭代器 读写操作,并能向前和向后操作 读写,支持++、–,
随机访问迭代器 读写操作,可以以跳跃的方式访问任意数据,功能最强的迭代器 读写,支持++、–、[n]、-n、<、<=、>、>=
  1. 输入迭代器(Input Iterator):这种迭代器只能用于读取数据,它允许以顺序方式逐个访问元素,但不支持对元素进行写操作。例如,std::istream_iterator 是一个输入迭代器,用于从输入流中读取数据。
  2. 输出迭代器(Output Iterator):这种迭代器只能用于写入数据,它允许以顺序方式逐个写入元素,但不支持读取元素。例如,std::ostream_iterator 是一个输出迭代器,用于向输出流中写入数据。
  3. 前向迭代器(Forward Iterator):这种迭代器支持输入和输出操作,可以在集合中前后移动,并对元素进行读写操作,但只能遍历集合一次。例如,std::forward_liststd::unordered_set 的迭代器就属于前向迭代器。
  4. 双向迭代器(Bidirectional Iterator):这种迭代器比前向迭代器更强大,除了支持前向和后向移动外,还可以反向遍历集合。例如,std::liststd::set 的迭代器就属于双向迭代器。
  5. 随机访问迭代器(Random Access Iterator):这种迭代器提供了最强大的功能,除了支持前向、后向和随机移动外,还可以通过迭代器进行算术计算,实现跳跃式访问集合中的元素。例如,std::vectorstd::array 的迭代器就属于随机访问迭代器。

不同类型的迭代器支持的运算操作也略有不同。

各种迭代器支持的常见运算操作
  1. 输入迭代器(Input Iterator):支持以下操作:
    • *it获取迭代器指向的元素值
    • it++++it:将迭代器向前移动到下一个位置。
    • it == it2it != it2:比较两个迭代器是否相等或不相等。
  2. 输出迭代器(Output Iterator):支持以下操作:
    • *it = value:将值赋给迭代器指向的位置。
    • it++++it:将迭代器向前移动到下一个位置。
  3. 前向迭代器(Forward Iterator):除了支持输入迭代器和输出迭代器的所有操作之外,还支持以下操作:
    • it1 == it2it1 != it2:比较两个迭代器是否相等或不相等。
  4. 双向迭代器(Bidirectional Iterator):除了支持前向迭代器的所有操作之外,还支持以下操作:
    • it----it:将迭代器向后移动到前一个位置。
  5. 随机访问迭代器(Random Access Iterator):除了支持双向迭代器的所有操作之外,还支持以下操作:
    • it += nit -= n:将迭代器向前或向后移动 n 个位置。
    • it + nit - n:返回从迭代器开始向前或向后移动 n 个位置后的迭代器。
    • it1 - it2:计算两个迭代器之间的距离。
    • it[n]:返回迭代器指向的位置加上 n 的元素。

STL示例

容器 —— vector

创建vector容器对象,并且通过模板参数指定容器中存放的数据的类型:

vector<int>  v;

迭代器: vector::iterator

每一个容器都有自己的迭代器,迭代器是用来遍历容器中的元素

v.begin() 返回迭代器,这个迭代器指向容器中第一个数据
v.end() 返回迭代器,这个迭代器指向容器元素的最后一个元素的下一个位置
vector::iterator 拿到vector这种容器的迭代器类型

vector::iterator it 创建迭代器对象

算法—— for_each

使用STL提供标准遍历算法 头文件 algorith

for_each 是C++算法库中的一个函数,用于对容器或范围内的元素逐个进行某种操作(函数)。

函数原型如下:

template
UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f);

参数说明:

  • firstlast:表示一个范围,指定需要进行操作的元素的起始和结束位置。
  • f:是一个一元函数对象(unary function),用于对元素进行操作。该函数对象接受一个元素作为参数,并返回结果(可选)。

for_each 函数会遍历指定范围内的每一个元素,将每个元素传递给函数对象 f 进行处理。

示例

#include 
#include 

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::iterator 拿到vector这种容器的迭代器类型

	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提供标准遍历算法  头文件 algorithm
	for_each(v.begin(), v.end(), MyPrint);
}

int main() {

	test01();

	system("pause");

	return 0;
}

常用的算法函数

#include 是 C++ 中用于包含算法库的头文件。该头文件中包含了许多有用的算法函数,可以对容器、数组和其他数据结构进行各种操作,例如排序、查找、合并等。

使用 #include 可以使程序能够使用算法库中的函数。你可以根据需要选择适当的算法函数来处理数据,提高编程效率和代码可读性。

排序算法:
  • 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):将两个已排序的范围归并成一个有序范围。

你可能感兴趣的:(C,++,c++)