一、初识STL
1.1 STL概述
长久以来,软件界⼀直希望建⽴⼀种可重复利⽤的东⻄,以及⼀种得以制造出”可重复运⽤的东⻄”的⽅法,让程序员的⼼⾎不⽌于随时间的迁移,⼈事异动⽽烟消云散,从函(functions),类别(classes),函数库(functionlibraries),类别库(class libraries)、各种组件,从模块化设计,到⾯向对象(object oriented ),为的就是复⽤性的提升。
复⽤性必须建⽴在某种标准之上。但是在许多环境下,就连软件开发最基本的数据结构(data structures) 和算法(algorithm)都未能有⼀套标准。⼤量程序员被迫从事⼤量复的⼯作,竟然是为了完成前⼈已经完成⽽⾃⼰⼿上并未拥有的程序代码,这不仅是⼈⼒资源的浪费,也是挫折与痛苦的来源。
为了建⽴数据结构和算法的⼀套标准,并且降低他们之间的耦合关系,以提升各⾃的独⽴性、弹性、交互操作性(相互合作性,interoperability),诞⽣了STL。
1.2 STL的基本概念
STL(Standard Template Library)是C++标准库中的一个重要部分,它提供了一组通用的模板类和函数,用于实现常见的数据结构和算法。STL旨在提供高效、可重用、通用的编程工具,以简化C++程序的开发。
1.3 STL六⼤组件简介
STL被分为六大组件,分别是:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器 ,每个组件解决了特定的编程问题。以下是这六个组件的简介:
容器(Containers): 容器是用于存储和组织数据的数据结构。STL提供了多种容器,包括向量(vector)、链表(list)、双向链表(deque)、映射(map)、集合(set)等。容器的不同特点适用于不同的问题,例如,向量适合随机访问,链表适合插入和删除操作。
算法(Algorithms): 算法是应用于容器的操作集合。STL提供了一系列通用的算法,如排序、查找、交换、合并等。这些算法适用于不同类型的容器,从而实现代码的重用。
迭代器(Iterators): 迭代器用于遍历容器中的元素。它提供了类似指针的操作,允许访问容器中的元素。迭代器分为输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器,根据容器的特点选择不同的迭代器。
函数对象(Function Objects): 函数对象是可调用对象,可以像函数一样被调用。STL中的很多算法使用函数对象进行操作,如比较、排序、转换等。STL提供了多个函数对象类,也可以自定义函数对象。
配接器(Adapters): 配接器用于将容器或函数对象适配为不同类型的接口。STL提供了两种常见的配接器:堆栈(stack)和队列(queue)。
空间配置器 (Allocators): 空间配置器用于管理内存的分配和释放。STL提供了默认分配器,还可以自定义分配器以满足特定的内存管理需求。
1.4STL的优点
STL 是 C++的⼀部分,因此不⽤额外安装什么,它被内建在你的编译器之内。
STL 的⼀个重要特性是将数据和操作分离。数据由容器类别加以管理,操作则由可定制的算法定义。迭代器在两者之间充当“粘合剂”,以使算法可以和容器交互运作。程序员可以不⽤思考 STL 具体的实现过程,只要能够熟练使⽤STL 就 OK 了。这样他们就可以把精⼒放在程序开发的别的⽅⾯。
STL 具有⾼可重⽤性,⾼性能,⾼移植性,跨平台的优点。
⾼可重⽤性:STL 中⼏乎所有的代码都采⽤了模板类和模版函数的⽅式实现,这相⽐于传统的由函数和类组成的库来说提供了更好的代码重⽤机会。
⾼性能:如 map 可以⾼效地从⼗万条记录⾥⾯查找出指定的记录,因为 map 是采⽤红⿊树的变体实现的。
⾼移植性:如在项⽬ A 上⽤ STL 编写的模块,可以直接移植到项⽬ B 上。
二、STL三大组件
2.1容器
在C++的STL(Standard Template Library)中,容器(Containers)是用于存储和组织数据的数据结构。STL提供了多种不同类型的容器,每种容器都有不同的特点和用途。以下是STL中常见的容器:
向量(vector): 动态数组,支持快速的随机访问和尾部插入。在插入和删除元素时,效率较低。
链表(list): 双向链表,支持在任意位置高效地插入和删除元素,但不支持随机访问。
双向队列(deque): 双端队列,既可以在头部高效地插入和删除,也可以在尾部高效地插入和删除。
栈(stack): 后进先出(LIFO)的数据结构,支持在栈顶插入和删除元素。
队列(queue): 先进先出(FIFO)的数据结构,支持在队尾插入,在队头删除元素。
优先队列(priority_queue): 基于堆的数据结构,能够快速访问最大或最小元素。
映射(map): 关联数组,存储键-值对,支持通过键快速查找和插入元素。
集合(set): 存储唯一值的有序集合,支持高效地插入、删除和查找操作。
无序映射(unordered_map): 基于哈希表的关联数组,能够快速访问键-值对。
无序集合(unordered_set): 基于哈希表的唯一值集合,支持高效的插入、删除和查找操作。
2.2算法
在C++的STL(Standard Template Library)中,算法(Algorithms)是一组通用的函数,用于操作容器中的元素。STL提供了许多已经实现和优化的算法,可以用于不同类型的容器,从而实现代码的重用。这些算法可以大大简化编程任务,如排序、查找、合并等。以下是STL中常见的一些算法:
排序算法:
sort()
:对容器中的元素进行排序。stable_sort()
:稳定排序,保留相等元素的相对顺序。查找算法:
find()
:在容器中查找指定元素。binary_search()
:二分查找,用于有序容器。合并和拷贝算法:
merge()
:合并两个有序容器。copy()
:将一个容器的元素拷贝到另一个容器。删除和替换算法:
remove()
:从容器中移除指定值的元素。replace()
:将容器中的元素替换为指定值。遍历和操作算法:
for_each()
:遍历容器中的每个元素,执行指定操作。transform()
:对容器中的元素进行转换操作。计数和累积算法:
count()
:计算容器中指定值的数量。accumulate()
:累积容器中的元素。最大和最小算法:
max_element()
:找到容器中的最大元素。min_element()
:找到容器中的最小元素。洗牌和随机算法:
shuffle()
:对容器中的元素进行随机洗牌。random_shuffle()
:使用随机数引擎进行洗牌。
2.3迭代器
在C++的STL(Standard Template Library)中,迭代器(Iterators)是一种用于遍历容器中元素的抽象概念。迭代器提供了一种统一的方式来访问容器中的元素,而不需要关心容器的具体实现。STL中的算法使用迭代器来访问和操作容器中的元素,这样可以使算法与容器的实际类型解耦,提高了代码的可重用性和灵活性。
迭代器可以被视为一种类似于指针的对象,它可以指向容器中的某个元素,并允许对元素进行读取、写入和操作。根据容器的性质,迭代器可以分为不同的类型,包括以下几种:
输入迭代器(Input Iterator): 支持从容器中读取数据,但只能遍历一次,不能修改容器中的数据。例如:
vector
、list
。输出迭代器(Output Iterator): 支持向容器中写入数据,但也只能遍历一次。例如:
ostream_iterator
。前向迭代器(Forward Iterator): 支持从容器中读取数据,可以多次遍历,但不能反向遍历。例如:
forward_list
。双向迭代器(Bidirectional Iterator): 支持从容器中读取和写入数据,可以正向和反向遍历,但效率可能较低。例如:
list
。随机访问迭代器(Random Access Iterator): 具备前面所有类型的特性,同时还支持随机访问,即可以像指针一样进行加减操作。例如:
vector
。#include <iostream> #include <vector> using namespace std; int main() { vector<int> nums = {1, 2, 3, 4, 5}; // 使用迭代器遍历向量并打印元素 for (vector<int>::iterator it = nums.begin(); it != nums.end(); ++it) { cout << *it << " "; } cout << endl; return 0; }