一.map、set是怎么实现的,红黑树是怎么能够同时实现这两种容器? 为什么使用红黑树?
-
他们的底层都是以红黑树的结构实现,因此插入删除等操作都在O(logn)时间内完成,因此可以完成高效的插入删除;
-
在这里我们定义了一个模版参数,如果它是key那么它就是set,如果它是map,那么它就是map;底层是红黑树,实现map的红黑树的节点数据类型是key+value,而实现set的节点数据类型是value
-
因为map和set要求是自动排序的,红黑树能够实现这一功能,而且时间复杂度比较低。
二.map插入方式有哪几种?
1.用insert函数插入pair数据
mapStudent.insert(pair<int, string>(1, "student_one"));
2.用insert函数插入value_type数据
mapStudent.insert(map<int, string>::value_type (1, "student_one"));
3.在insert函数中使用make_pair()函数
mapStudent.insert(make_pair(1, "student_one"));
4.用数组方式插入数据
mapStudent[1] = "student_one";
三.map为什么没有reserve?
std::map
是 C++ 标准模板库(STL)中的关联容器之一,它使用红黑树来实现键值对的有序存储。在 std::map
中,元素会按照键的自然顺序进行排序,并且不能重复。
std::map
没有提供 reserve()
方法的原因是,与其它容器(如 std::vector
、std::unordered_map
等)不同,std::map
的内部数据结构是基于红黑树实现的,它并没有连续分配内存的需求。因此,在创建一个空的 std::map
时,并不需要保留一定的容量。
reserve()
方法通常用于容器预先分配一定的存储空间。而对于 std::map
来说,由于其内部的红黑树结构不需要连续的存储空间,因此不存在重新分配和拷贝的问题,也就没有必要提供 reserve()
方法。
如果你想在创建 std::map
时指定初始大小,可以通过传递一个已有容器作为构造函数的参数来实现:
std::map<Key, Value> myMap(existingContainer.begin(), existingContainer.end());
总之,std::map
不提供 reserve()
方法是因为其内部数据结构的特点决定了它不需要连续的存储空间,因此不需要在创建时保留一定的容量。
四.map什么时候迭代器失效?
1.插入元素:如果在迭代过程中向std::map
中插入新的键值对,则所有之前的迭代器都会失效,因为插入操作可能导致内部数据结构重新组织,改变树的结构。
std::map<int, std::string> myMap;
std::map<int, std::string>::iterator it = myMap.begin();
myMap[1] = "One"; // 这里插入新元素
// 现在迭代器 it 可能已经失效
2.删除元素:如果在迭代过程中删除了元素,则指向被删除元素的迭代器也会失效。
std::map<int, std::string> myMap;
myMap[1] = "One";
myMap[2] = "Two";
std::map<int, std::string>::iterator it = myMap.begin();
myMap.erase(1); // 删除元素
// 现在迭代器 it 可能已经失效
3.改变键的值:如果在迭代过程中修改了std::map
中已存在的键的值,迭代器通常会保持有效,因为它们仍然指向相同的键,但是请小心,这可能会改变键的排序位置。
std::map<int, std::string> myMap;
myMap[1] = "One";
std::map<int, std::string>::iterator it = myMap.begin();
it->second = "NewOne"; // 修改键值
// 迭代器 it 仍然有效,但排序位置可能已经改变
五.STL中map、set、unordered_set、unordered_map的区别和应用场景
map
map支持键值的自动排序,底层机制是红黑树,红黑树的查询和维护时间复杂度均为 O(logn) ,但是占用空间比较大,因为每个节点都要保持父节点、孩子节点及颜色信息。
set
set与map类似,set的底层实现通常也是红黑树。set是一种特殊的Map,只有键没有值。
unordered_map
unordered_map是C++ 11 新添加的容器,底层机制是哈希表,通过hash函数计算元素位置,其查询时间复杂度为 O(1) ,维护时间与 buclet 桶所维护的 list 长度有固安,但是建立 hash 表耗时较大。
unordered_set
unordered_set与unordered_map 类似,unordered_set的底层实现通常也是哈希表。unordered_set 是一种特殊的unordered_map,只有键没有值。
从底层机制和特点可以看出:map适用于有序数据的应用场景,unordered_map适用于高效查询的应用场景。