上期回顾: 【C++】模板编程和泛型编程
个人主页:C_GUIQU
归属专栏:C++
目录
正文
1. 引言
C++标准模板库(STL)是一组功能强大的模板类和函数,它提供了通用的算法和数据结构,极大地提升了C++编程的效率。STL涵盖了多种常用的数据结构和算法,让开发者能够将更多精力集中在程序的业务逻辑上,无需从头开始实现这些基础功能。
2. STL的主要组件
2.1 容器(Containers)
容器是用于存储和管理数据的对象,STL提供了多种不同类型的容器,每种容器都具备独特的用途和性能特点。
2.1.1 vector(动态数组)
- 概述:
vector
是一个动态大小的数组,它在内存中连续存储元素,类似于普通的数组,但可以在运行时根据需要动态地增加或减少其大小。这使得它在需要频繁访问元素且元素数量可能变化的场景中非常实用。 - 特性:
- 支持随机访问:可以通过下标运算符
[]
直接访问容器中的任意元素,就像访问普通数组一样,访问时间复杂度为常数级别 O ( 1 ) O(1) O(1)。 - 动态扩容:当向
vector
中添加元素超过其当前容量时,它会自动重新分配一块更大的内存空间,并将原有元素复制过去,这个过程可能会导致一定的性能开销,但通常情况下扩容策略能较好地平衡性能和空间利用。 - 内存连续:元素在内存中是连续存储的,这对于需要利用内存局部性原理来提高访问效率的场景很有优势,比如遍历操作。
- 支持随机访问:可以通过下标运算符
- 代码示例:
#include <iostream>
#include <vector>
int main() {
// 创建一个空的vector,存储整数
std::vector<int> myVector;
// 向vector中添加元素
myVector.push_back(10);
myVector.push_back(20);
myVector.push_back(30);
// 输出vector的大小(当前元素个数)
std::cout << "vector大小: " << myVector.size() << std::endl;
// 遍历vector并输出元素
for (int i = 0; i < myVector.size(); ++i) {
std::cout << myVector[i] << " ";
}
// 通过下标访问并修改特定元素
myVector[1] = 25;
std::cout << "\n修改后vector的元素: ";
for (int i : myVector) {
std::cout << i << " ";
}
return 0;
}
2.1.2 list(双向链表)
- 概述:
list
是一个双向链表容器,每个节点包含数据元素以及指向前一个节点和后一个节点的指针。它在插入和删除元素方面具有出色的性能,尤其适用于频繁进行此类操作的场景,因为这些操作只需修改相关节点的指针,而不需要移动大量元素。 - 特性:
- 高效的插入和删除:在链表中的任意位置插入或删除元素的时间复杂度均为常数级别 O ( 1 ) O(1) O(1),相比之下,在数组中进行插入和删除操作可能需要移动大量后续元素,时间复杂度较高。
- 不支持随机访问:由于链表的存储结构特点,无法像数组那样通过下标直接访问元素,要访问链表中的某个元素,需要从表头或表尾开始逐个遍历节点,访问第 n n n个元素的时间复杂度为 O ( n ) O(n) O(n)。
- 内存非连续:节点在内存中的存储位置是不连续的,这与
vector
的连续存储不同,所以在利用内存局部性方面相对较弱。
- 代码示例:
#include <iostream>
#include <list>
int main() {
// 创建一个空的list,存储字符
std::list<char> myList;
// 向list中添加元素
myList.push_back('a');
myList.push_back('b');
myList.push_back('c');
// 输出list的大小
std::cout << "list大小: " << myList.size() << std::endl;
// 在列表头部插入元素
myList.push_front('x');
// 遍历list并输出元素
for (char c : myList) {
std::cout << c << " ";
}
// 删除列表中的特定元素
myList.remove('b');
std::cout << "\n删除元素后list的元素: ";
for (char c : myList) {
std::cout << c << " ";
}
return 0;
}
2.1.3 deque(双端队列)
- 概述:
deque
(发音为“deck”)是一种双端队列容器,它结合了vector
和list
的一些优点。它可以在两端高效地插入和删除元素,同时也支持一定程度的随机访问,虽然其随机访问性能不如vector
。 - 特性:
- 双端操作高效:在队列的两端(前端和后端)插入和删除元素的时间复杂度均为常数级别 O ( 1 ) O(1) O(1),这使得它在需要频繁在两端进行操作的场景中很有用,比如实现一个队列或栈的数据结构。
- 支持随机访问:可以通过下标运算符进行随机访问,但相比
vector
,其随机访问性能稍差,因为deque
内部的存储结构相对复杂一些,访问第 n n n个元素的时间复杂度通常被认为是接近常数级别,但在最坏情况下可能达到 O ( n ) O(n) O(n)。 - 动态内存管理:与
vector
类似,deque
也能根据需要动态地调整其存储容量,但它的扩容机制与vector
有所不同,以适应其双端操作的特点。
- 代码示例:
#include <iostream>
#include <deque>
int main() {