C++标准模板库(STL)容器、算法、迭代器
一. STL(标准模板库)的概述
定义:STL(Standard Template Library)是C++标准库的一部分,它提供了一系列通用的模板类和函数,用于处理常见的编程任务,如数据存储、排序、搜索等,旨在提高代码的复用性和效率。
组成部分:STL主要由容器(Containers)、算法(Algorithms)和迭代器(Iterators)三大组件构成,此外还包括函数对象(Function objects)、适配器(Adapters)和分配器(Allocators)等辅助组件。
二. 容器(Containers)
1. 顺序容器 vector:
vector是一个动态大小的数组,可以在末尾快速插入和删除元素。它在内存中是连续存储的,这使得随机访问元素非常高效(时间复杂度为$O(1)$),但在中间插入或删除元素可能会比较慢(平均时间复杂度为$O(n)$,其中$n$是容器中的元素个数)。
#include <vector> #include <iostream> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); for (size_t i = 0; i < v.size(); i++) { std::cout << v[i] << " "; } return 0; }
2. 顺序容器 list:
list是一个双向链表,它的每个节点包含一个元素和指向前一个节点和后一个节点的指针。在list中任意位置插入和删除元素都非常快(时间复杂度为$O(1)$),但随机访问元素比较慢(时间复杂度为$O(n)$)。
#include <list> #include <iostream> int main() { std::list<int> l; l.push_back(1); l.push_back(2); l.push_back(3); for (auto it = l.begin(); it!= l.end(); ++it) { std::cout << *it << " "; } return 0; }
3. 顺序容器 deque(双端队列):
deque(发音为“deck”)是一种双端队列,它类似于vector,但在两端插入和删除元素都非常高效(时间复杂度为$O(1)$)。deque内部的存储结构可能不是连续的,而是由多个固定大小的块组成。
#include <deque> #include <iostream> int main() { std::deque<int> d; d.push_back(1); d.push_front(0); for (size_t i = 0; i < d.size(); i++) { std::cout << d[i] << " "; } return 0; }
4. 关联容器 set:
set是一个有序的集合,其中的元素是唯一的。它基于红黑树实现,插入、删除和查找操作的时间复杂度都是$O(\log n)$。set会自动对元素进行排序。
#include <set> #include <iostream> int main() { std::set<int> s; s.insert(3); s.insert(1); s.insert(2); for (auto it = s.begin(); it!= s.end(); ++it) { std::cout << *it << " "; } return 0; }
5. 关联容器 map:
map是一个键 - 值对的有序集合,每个键在map中是唯一的。它基于红黑树实现,插入、删除和查找操作的时间复杂度都是$O(\log n)$。可以通过键快速查找对应的值。
#include <map> #include <iostream> int main() { std::map<int, int> m; m.insert(std::make_pair(1, 10)); m.insert(std::make_pair(2, 20)); m.insert(std::make_pair(3, 30)); for (auto it = m.begin(); it!= m.end(); ++it) { std::cout << it->first << " " << it->second << " "; } return 0; }
6. 关联容器 unordered_set、关联容器 unordered_map(C++11及以上):
这两个容器分别是set和map的无序版本,它们基于哈希表实现。插入、删除和查找操作在平均情况下的时间复杂度为$O(1)$,但在最坏情况下可能为$O(n)$。由于是无序的,所以不会对元素进行自动排序。
#include <unordered_set> #include <unordered_map> #include <iostream> int main() { std::unordered_set<int> us; us.insert(3); us.insert(1); us.insert(2); for (auto it = us.begin(); it!= us.end(); ++it) { std::cout << *it << " "; } std::unordered_map<int, int> um; um.insert(std::make_pair(1, 10)); um.insert(std::make_pair(2, 20)); um.insert(std::make_pair(3, 30)); for (auto it = um.begin(); it!= um.end(); ++it) { std::cout << it->first << " " << it->second << " "; } return 0; }
三. 算法(Algorithms)
1. 排序算法 std::sort:
对给定范围内的元素进行排序。它是一个快速排序的实现,平均时间复杂度为$O(n\log n)$,最坏情况下为$O(n^{2})$,但在实际应用中通常表现良好。
#include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {3, 1, 2}; std::sort(v.begin(), v.end()); for (auto num : v) { std::cout << num << " "; } return 0; }
2. 查找算法 std::find:
功能:在给定范围内查找指定元素,如果找到则返回指向该元素的迭代器,否则返回范围末尾的迭代器。
#include <algorithm> #include <vector> #include <iostream> int main() { std::vector<int> v = {1, 2, 3}; auto it = std::find(v.begin(), v.end(), 2); if (it!= v.end()) { std::cout << "Element found"; } else { std::cout << "Element not found"; } return 0; }
四. 迭代器(Iterators)
定义与功能:迭代器是一种类似于指针的对象,用于遍历容器中的元素。不同类型的容器提供不同类型的迭代器,但它们都遵循一定的规范,使得可以使用相同的算法来操作不同类型的容器。
分类:
输入迭代器:可以从容器中读取元素,支持++(向前移动)操作和*(解引用)操作,但不支持多次解引用同一元素,也不支持--(向后移动)操作。
输出迭代器:用于向容器中写入元素,支持++操作和*操作,但解引用操作只能用于赋值,不能读取元素。
前向迭代器:兼具输入迭代器和输出迭代器的功能,并且支持多次解引用同一元素。
双向迭代器:在前向迭代器的基础上,支持--操作,可以双向遍历容器。
随机访问迭代器:除了双向迭代器的功能外,还支持随机访问元素,如it + n、it - n等操作,像vector容器提供的迭代器就是随机访问迭代器。
五. 函数对象(Function objects)、适配器(Adapters)和分配器(Allocators)
函数对象(Function objects):也称为仿函数,是一个类,其重载了()运算符,使得类的对象可以像函数一样被调用。例如:
class Add { public: int operator()(int a, int b) { return a + b; } }; int main() { Add add; int result = add(1, 2); std::cout << result << " "; return 0; }
适配器(Adapters):用于修改或组合其他组件的行为。例如,std::bind是一个函数适配器,它可以绑定函数的部分参数,创建一个新的可调用对象。
分配器(Allocators):负责为容器分配和回收内存。默认的分配器std::allocator在大多数情况下能够满足需求,但在一些特殊场景下,如需要定制内存分配策略时,可以创建自己的分配器。
C++编程语言基础
- C++:从入门到工作的教程
- 这是我的第一个 C++程序!
- C++中main函数有什么作用?
- C++中 #include 指令的作用
- C++中常用的预处理指令
- C++中 iostream 头文件定义了什么
- C++名称空间(namespace)
- C++标准库中 std 命名空间定义了些什么
- C++常用的头文件
- C++源代码的发布方式
- C++变量名的定义、变量的作用、使用规范
- C++的关键字列表
- C++数据类型:整型(整数类型)
- 二进制补码、原码、反码
- C++数据类型:char字符型(整数类型)
- ASCII码表及C++字符函数库(cctype)
- 计算机汉字编码
- C++数据类型:bool类型(整数类型)
- C++中 const 限定符
- C++数据类型:浮点数
- C++运算符:算术运算符
- C++运算符:类型转换规则
- 计算机数据存储大小端模式
- C++运算符:位运算 与 bitset类库
- C++运算符:关系运算符与逻辑运算符
- C++流程控制:顺序、选择、循环、跳转语句
- C++函数的定义、参数传递、重载、嵌套
- C++数组:一维、二维、多维数组的运用
- C-style字符串、库函数 与 std::string对象
- C++数据类型:结构体(struct)
- C++数据类型:联合体(union)
- C++数据类型:枚举(enum)
- C++数据类型别名:typedef
- C++指针
- C++内存操作符:new分配 与 delete释放
- C++标准模板库(STL)容器、算法、迭代器
- C++标准模板库(STL)vector顺序容器
- C++标准模板库(STL)array固定容器
- C++标准模板库(STL)list双向链表容器
- C++标准模板库(STL)deque双端队列
- C++标准模板库(STL)集合 set 关联容器
- C++标准模板库(STL)map关联容器
- C++标准模板库(STL)unordered_set
- C++标准模板库(STL)unordered_map
- C++标准模板库(STL)algorithm算法库
- C++文件操作
- C++数学库(cmath)数学常量与数学函数
- C++模板:函数模板、类模板
- C++与SQLite3联合打造实用的应用程序
- C++实战开发中常用的库(概述)
- 第二部分:C++面向对象编程
- C++:类的定义与声明、类对象应用
- 第三部分:数据结构与算法(概述)
- 第一部分:C++语言简介与学习路线