这里写目录标题
- [C++ STL(标准模板库,Standard Template Library)简介](#C++ STL(标准模板库,Standard Template Library)简介)
- 迭代器
- [STL- 常用容器](#STL- 常用容器)
-
- string容器
-
- [C 风格字符串与 std::string 的区别](#C 风格字符串与 std::string 的区别)
- vector容器
- deque容器
- [Stack 容器(栈)](#Stack 容器(栈))
- [Queue 容器(队列)](#Queue 容器(队列))
- list容器
- [Set 和 Multiset 容器](#Set 和 Multiset 容器)
-
- [Set 容器](#Set 容器)
- [Multiset 容器](#Multiset 容器)
- [map/ multimap容器](#map/ multimap容器)
-
- [map 容器](#map 容器)
- [multimap 容器](#multimap 容器)
C++ STL(标准模板库,Standard Template Library)简介
STL 包括以下三大部分:
容器(Containers)
提供存储和管理数据的结构,如动态数组、链表、哈希表等。
算法(Algorithms)
提供对容器进行操作的通用算法,如排序、查找、复制等。
迭代器(Iterators)
提供一种统一的方式来访问容器中的元素,连接容器和算法。
迭代器
C++ STL 中的迭代器类型
C++ STL 提供了不同类型的迭代器来适应不同容器的访问需求,主要包括以下几种:
- 输入迭代器(Input Iterator)
- 功能:只能用来遍历数据。
- 特性:只能读取数据,不能修改。
- 示例 :
istream_iterator
用于从流中读取数据。
- 输出迭代器(Output Iterator)
- 功能:只能用来向容器中写入数据。
- 特性:不能读取数据。
- 示例 :
ostream_iterator
用于向流中写入数据。
- 前向迭代器(Forward Iterator)
- 功能:可以遍历数据,并支持前一个和下一个元素的访问。
- 特性:可以用于读取和修改数据。
- 示例 :
vector<int>::iterator
是一个前向迭代器。
- 双向迭代器(Bidirectional Iterator)
- 功能:支持遍历数据,支持前一个和下一个元素的访问。
- 特性:可以向前和向后移动。
- 示例 :
list<int>::iterator
是一个双向迭代器。
- 随机访问迭代器(Random Access Iterator)
- 功能:支持快速访问任何位置的元素(O(1) 时间复杂度)。
- 特性:可以向前和向后移动,支持加法和减法操作。
- 示例 :
array<int>::iterator
和vector<int>::iterator
是随机访问迭代器。
如何获得迭代器
迭代器通常由容器的成员函数提供,常见的获取迭代器的方法如下:
begin():返回指向容器第一个元素的迭代器。
end():返回指向容器最后一个元素之后位置的迭代器(即尾后迭代器)。
c
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> myVector = {1, 2, 3, 4, 5};
// 获取容器的迭代器
vector<int>::iterator it = myVector.begin();
// 输出第一个元素
cout << *it << endl; // 输出 1
// 移动迭代器,指向第二个元素
++it;
cout << *it << endl; // 输出 2
return 0;
}
迭代器的常见操作
操作类别 | 操作 | 描述 |
---|---|---|
访问元素 | *it |
解引用迭代器,获取当前迭代器指向的元素。 |
it->member |
通过箭头操作符访问迭代器指向元素的成员。 | |
移动迭代器 | ++it |
前进到下一个元素。 |
it++ |
后进到下一个元素(后置自增)。 | |
--it |
回退到前一个元素(双向和随机访问迭代器支持)。 | |
it + n 或 it += n |
将迭代器前进 n 个位置(仅限随机访问容器)。 | |
it - n 或 it -= n |
将迭代器后退 n 个位置(仅限随机访问容器)。 | |
比较迭代器 | it1 == it2 |
检查两个迭代器是否指向同一个位置。 |
it1 != it2 |
检查两个迭代器是否不指向同一个位置。 | |
it1 < it2 , it1 > it2 |
检查迭代器的位置相对大小(仅限随机访问迭代器)。 | |
访问容器的大小 | container.size() |
获取容器中元素的个数。 |
container.empty() |
检查容器是否为空。 | |
其他操作 | it[3] |
随机访问迭代器支持的索引操作(仅限随机访问迭代器)。 |
it + n |
前进 n 个位置的迭代器(仅限支持随机访问的容器)。 |
STL- 常用容器
string容器
string管理char*所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责。
C 风格字符串与 std::string 的区别
特性 | C 风格字符串 | std::string |
---|---|---|
内存管理 | 手动管理,易出错 | 自动管理,安全可靠 |
功能 | 功能有限,需手写操作 | 提供丰富的方法和接口 |
大小动态调整 | 不支持,需重新分配 | 自动调整 |
操作安全性 | 易越界,需手动检查 | 提供边界检查,较安全 |
vector容器
std::vector 是 C++ STL(标准模板库)中最常用的顺序容器之一,它实现了动态数组功能,支持随机访问和自动调整大小。它的底层实现是一个连续的内存块 ,因此能高效地支持随机访问。
deque容器
deque 是 C++ STL 提供的一种 双端队列容器,全称是 Double-ended Queue。它可以在 头部和尾部 高效地进行插入和删除操作,同时也支持随机访问,是一种灵活的序列容器。与 vector 的连续存储不同,deque 通常实现为分段存储,便于双端高效操作。
分段存储结构:与 vector 的连续存储不同,deque 通常实现为分段存储,便于双端高效操作。
Stack 容器(栈)
stack 是 C++ STL 提供的一种 栈容器适配器,它是一种**后进先出(LIFO, Last In First Out)**的数据结构。栈只能在一端进行插入(push)和删除(pop)操作。栈通常用于需要按顺序处理数据的情况,最后被插入的数据会最先被处理。
Queue 容器(队列)
queue 是 C++ STL 提供的一种 队列容器适配器,它是一种 先进先出(FIFO, First In First Out) 数据结构。队列的数据插入发生在队尾,数据删除发生在队头。与栈不同,队列保证了元素的插入和删除顺序。
list容器
C++ STL 提供的 list 容器是一个 双向链表 容器。与 vector 或 deque 等数组类型容器不同,list 容器使用链表结构来存储元素,这意味着每个元素都包含对前一个元素和后一个元素的指针。
list 提供了高效的插入和删除操作,尤其是在容器的中间部分。其主要优势在于能够高效地进行元素的插入、删除,而不会像 vector 一样涉及到大量的元素移动。
不支持随机访问 : 由于是链表结构,list 不支持通过下标访问元素,访问元素需要通过迭代器遍历链表。
总结:STL中List和vector是两个最常被使用的容器,各有优缺点
Set 和 Multiset 容器
C++ STL 中的 set 和 multiset 容器用于存储一组 不重复或允许重复 的元素。它们是 关联容器,即容器中的元素会根据某种顺序自动排序(通常是升序),并且支持高效的查找、插入和删除操作。
Set 容器
set 是一个 集合容器,它自动排序 并且不允许元素重复。在 set 中,所有的元素都是唯一的。set 中的元素按指定的顺序排列(默认是升序 ),并且不能直接通过索引访问元素。
利用仿函数可以指定set容器的排序规则
c
class MyCompare
{
public:
bool operator()(int v1, int v2) {
return v1 > v2;
}
};
c
void test01()
{
set<int> s1;
s1.insert(10);
s1.insert(40);
s1.insert(20);
s1.insert(30);
s1.insert(50);
//默认从小到大
for (set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
cout << *it << " ";
}
cout << endl;
//指定排序规则
set<int,MyCompare> s2;
s2.insert(10);
s2.insert(40);
s2.insert(20);
s2.insert(30);
s2.insert(50);
for (set<int, MyCompare>::iterator it = s2.begin(); it != s2.end(); it++) {
cout << *it << " ";
}
cout << endl;
}
对于自定义数据类型,set必须指定排序规则才可以插入数据
Multiset 容器
multiset 是一个 允许重复元素 的容器。它与 set 非常类似,不同之处在于 multiset 允许多个相同的元素存储在容器中。与 set 一样,multiset 中的元素会自动按顺序排列。
pair对组创建
在 C++ 中,pair 是一个标准库模板类,用于存储两个数据元素,可以是不同类型的数据。pair 是非常有用的数据结构,尤其在处理关联容器(如 map 和 multimap)时,用来存储键值对。
pair 类介绍pair 是 C++ STL 中的一种简单的容器,它包含了两个值成员:第一个值 first 和第二个值 second。pair 类定义在 头文件中。
map/ multimap容器
两者都自动按键进行排序,默认是升序排序,但可以通过自定义比较器来修改排序规则。对于自定义数据类型,map必须要指定排序规则,同set容器
map 容器
map 是一个有序的关联容器,它存储的元素是唯一的(每个键只能出现一次)。map 按照键的顺序自动对元素进行排序,默认使用 operator< 比较键。
特点:
- map中所有元素都是pair
- 键是唯一的:每个键在 map 中只能出现一次。
- 有序:map 中的元素按键的升序排列(可以自定义排序规则)。
- 查找、插入和删除操作的时间复杂度为 O(log n),基于红黑树实现。
multimap 容器
multimap 是与 map 非常相似的一个容器,区别在于它允许键的重复性,即一个键可以与多个值关联。multimap 也会按照键的顺序自动排序,但不同的是,它不会强制键值的唯一性。
特点:
- 键可以重复:同一个键可以与多个值关联。
- 有序:multimap 中的元素按键的升序排列(可以自定义排序规则)。
- 查找、插入和删除操作的时间复杂度为 O(log n),基于红黑树实现。
c
// 自定义比较器,按降序排序
struct DescendingComparator {
bool operator()(int a, int b) const {
return a > b; // 降序排列
}
};
int main() {
// 使用自定义比较器的 map
map<int, string, DescendingComparator> myMap;
myMap[1] = "apple";
myMap[2] = "banana";
myMap[3] = "cherry";
// 遍历 map,输出按降序排列的元素
for (const auto& entry : myMap) {
cout << entry.first << " -> " << entry.second << endl;
}
return 0;
}