C++ STL 相关 部分笔记
本人菜鸟,个人学习笔记,如有错误还请指教。
STL 标准模板库
STL提供了一组表示容器,迭代器,函数对象和算法的模板。
目录
STL教程:C++ STL快速入门(非常详细) 语言中文网
目录结构
C++ STL是什么,有什么用?
[C++ STL是什么,有什么用?C语言中文网](http://c.biancheng.net/view/6557.html)
C++ STL容器是什么
本章主要讲解STL标准库中所有的序列式容器,包括 array、vector、deque、list 和 forward_list 容器。
简单的理解容器,它就是一些模板类的集合,但和普通模板类不同的是,容器中封装的是组织数据的方法(也就是数据结构)。STL 提供有 3 类标准容器,分别是序列容器、排序容器和哈希容器,其中后两类容器有时也统称为关联容器。
(C++ Primer中文版 译为 顺序容器)
C++ STL中的顺序容器是什么
[C++序列式容器(STL序列式容器)是什么 C语言中文网](http://c.biancheng.net/view/409.html)所谓STL序列式容器,其共同的特点是不会对存储的元素进行排序,元素排列的顺序取决于存储它们的顺序。
vector相关
vector(result_set.begin(),result_set.end()); 它怎么能这样初始化一个vector呢?
这是通过迭代器范围初始化vector的方法,它可以从一个容器(比如set、list、array等)初始化vector。具体来说,vector的构造函数可以接受一个指向第一个元素的迭代器和一个指向最后一个元素下一个位置的迭代器,将它们之间的元素拷贝到新的vector中。
在提供的代码中,result_set是一个set类型的对象。通过调用begin()和end()方法获取迭代器,可以得到一个指向set中第一个元素和最后一个元素下一个位置的迭代器。将这两个迭代器作为参数传递给vector的构造函数,就可以将set中的元素拷贝到新的vector中。
这种方式还可以用于拷贝其他容器中的元素到vector中,只要这些容器提供了begin()和end()方法来获取迭代器。
C++ STL vector 删除元素
C++ STL vector删除元素的几种方式(超级详细) C语言中文网
| remove() | 删除容器中所有和指定元素值相等的元素,并返回指向最后一个元素下一个位置的迭代器。值得一提的是,调用该函数不会改变容器的大小和容量。
STL关联式容器
STL关联式容器本章将介绍 STL 标准库中另一类容器,即关联式容器,包括 map、multimap、set 以及 multiset 这 4 种容器。
关联式容器查找、访问、插入和删除指定元素的效率更高。
除此之外,序列式容器中存储的元素默认都是未经过排序的,而使用关联式容器存储的元素,默认会根据各元素的键值的大小做升序排序。
multiset的介绍及使用
#include <iostream>
#include <set>
using namespace std;
int main()
{
int array[] = { 0, 2, 1, 4, 3, 6, 5, 7, 8, 9, 0, 7, 6, 8, 9, 5, 4, 2, 1, 3 };
multiset<int> ms(array, array + sizeof(array) / sizeof(array[0]));
for (auto& e : ms)
{
cout << e << " ";
}
cout << endl;
system("pause");
return 0;
}
在这段代码中,multiset
在初始化 multiset 对象时,使用了从数组 array 到 array + sizeof(array) / sizeof(array[0]) 的迭代器区间,这样就将数组中的元素逐一插入到 multiset 容器中。这个迭代器区间通过array指向数组首元素,array + sizeof(array) / sizeof(array[0]) 指向整个数组的结尾,从而描述了该数组的所有元素。 (其中, sizeof(array) 表示数组所占用的字节数,sizeof(array[0]) 表示数组中每个元素所占用的字节数,因此 sizeof(array) / sizeof(array[0]) 就是数组中元素的个数)。
因此,这行代码 multiset
接下来,程序使用了范围 for 循环打印容器中所有的元素,每个元素之间用空格隔开。最后,程序调用了 system("pause") 命令,以便您能够在程序执行完毕后查看最终输出。
unordered_set插入重复元素会怎样
在C++的unordered_set中,插入重复元素不会导致数据结构中存在重复。插入已经存在的值会被忽略,unordered_set所维护的数据结构保持不变。
具体而言,当我们要插入一个重复元素时,unordered_set的底层实现将查找表中已经存在该元素的情况,如果该元素被发现,插入操作直接被忽略。
因此,在插入重复元素后,unordered_set所维护的元素个数以及内部数据结构都不会发生任何变化,同时返回值表明插入操作失败,因为元素已经存在。
C++ STL中的 multimap 有重复值的话,他们的Value怎么分配?
在 multimap 中,插入元素时并不会去判断这个元素是否已经存在于容器中,因此同一个 Key 值可以对应多个 Value。当然,这些 Value 值会被存储在不同的迭代器中,所以只要它们的键值相同,它们就属于同一个 Key,而可以有多个 Value 与之对应。
因为 multimap 具有与 map 类似的特点,所以他们所使用的 STL基数树(红黑树)也是用于按照某种特定顺序存储键值的。multimap 是根据 Key 值进行排序,因此同一个键值的多个 Value 会按照指定的排序方式进行排序。
当处理一个键值对应的多个 Value 时,使用迭代器依次访问它们。通过迭代器可以访问到对应的每一个 Value。如果要删除某个键值对应的一个 Value,可以使用迭代器从容器中删除;如果需要删除一个键值对应的所有 Value,可以使用 multimap::erase 函数。
需要注意的是,multimap 不支持下标操作符,而 map 支持,这是它们之间的一个重要区别。如果需要使用下标操作符,应该考虑使用 map 而不是 multimap。
C++ STL unordered_map容器用法详解
C++ STL unordered_map容器用法详解 C语言中文网
unordered_map 容器和 map 容器仅有一点不同,即 map 容器中存储的数据是有序的,而 unordered_map 容器中是无序的。
值得一提的是,unordered_map 容器在<unordered_map>头文件中,并位于 std 命名空间中。因此,如果想使用该容器,代码中应包含如下语句:
#include <unordered_map>
using namespace std;
虽然std::set、std::multiset 的底层实现是红黑树,不是哈希表,
std::set、std::multiset 使用红黑树来索引和存储,不过给我们的使用方式,还是哈希法的使用方式,即key和value。所以使用这些数据结构来解决映射问题的方法,我们依然称之为哈希法。 map也是一样的道理。
std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。同理,std::map 和std::multimap 的key也是有序的(这个问题也经常作为面试题,考察对语言容器底层的理解)。
当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。
红黑树是一种自平衡二叉搜索树,它的节点被标记为红色或黑色。红黑树的特点包括:
- 每个节点都是红色或黑色。
- 根节点是黑色的。
- 每个叶子节点(NIL节点,空节点)是黑色的。
- 如果一个节点是红色的,则它的两个子节点都是黑色的。
- 对于每个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点。
这些特点保证了红黑树的平衡性,使得它的插入、删除和查找操作都能在对数时间内完成。因此,红黑树被广泛应用于各种数据结构和算法中,如C++ STL的map和set容器。
sort函数
C++中的sort函数默认是按从小到大的顺序进行排序的。
如果您想按从大到小的顺序进行排序,可以自定义比较函数(也称为比较器或者排序规则),并将其作为sort函数的第三个参数传入。比较函数需要返回一个布尔值,表示两个元素的大小关系。
例如,如果您有一个整数数组nums,想要按从大到小的顺序进行排序,可以写一个比较函数如下:
bool cmp(int a, int b)
{
return a > b;
}
然后在sort函数中调用该函数:
sort(nums.begin(), nums.end(), cmp);
这样就可以按从大到小的顺序进行排序了。
另外,也可以使用lambda表达式来定义比较函数,例如:
sort(nums.begin(), nums.end(), [](int a, int b) { return a > b;} );
这样也可以实现从大到小的排序。