C++一分钟之-map与set容器详解

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
大数据开发治理平台 DataWorks,不限时长
实时计算 Flink 版,5000CU*H 3个月
简介: 【6月更文挑战第21天】C++ STL的`map`和`set`是基于红黑树的关联容器,提供有序存储和高效查找。`map`存储键值对,键唯一,值可重复;`set`仅存储唯一键。两者操作时间复杂度为O(log n)。常见问题包括键的唯一性和迭代器稳定性。自定义比较函数可用于定制排序规则,内存管理需注意适时释放。理解和善用这些工具能提升代码效率。

在C++ Standard Template Library(STL)中,mapset作为关联容器,为开发者提供了键值对存储和唯一键集合管理的强大工具。它们底层通常基于红黑树实现,保证了元素的有序性和对数时间复杂度的查找效率。本文将深入浅出地解析mapset的使用方法、常见问题及其规避策略,并通过代码示例加以说明。
image.png

1. map:键值对的天堂

map容器存储键值对,其中键是唯一的,值可以重复。键用于排序和查找,值则存储实际数据。map中的元素默认按照键的升序排列。

常见问题与避免策略:

  • 键的唯一性:尝试插入已存在的键会导致插入失败,而不是覆盖原有值。若需覆盖,请先检查键是否存在,再决定插入或更新。
std::map<std::string, int> myMap;
myMap["apple"] = 4; // 插入或更新
if (myMap.find("banana") != myMap.end()) {
   
   
    myMap.erase("banana"); // 删除后再插入实现覆盖效果
    myMap["banana"] = 2;
}
  • 性能考量:查找、插入和删除操作的时间复杂度均为O(log n),但频繁的插入和删除可能导致树的不平衡,影响性能。适度的重平衡(如通过迭代器失效后的自动调整)可以缓解这一问题。

2. set:无重复的键集合

set类似于map,但只存储键,没有对应的值,所有元素都是唯一的。它同样按照键的升序排列。

常见问题与避免策略:

  • 元素唯一性:试图插入重复元素将被忽略,这是set设计的初衷。确保插入前元素的唯一性,或利用此特性进行去重。
std::set<int> mySet;
mySet.insert(1); // 成功插入
mySet.insert(1); // 重复,不会插入
  • 迭代器稳定性:在setmap中,插入新元素或删除现有元素不会导致其他元素的迭代器失效,但插入或删除操作点的迭代器会失效。在遍历时谨慎操作集合。

3. 共同注意事项

  • 自定义比较函数:默认情况下,键按字典顺序排序。可以通过提供自定义比较函数或比较对象来自定义排序规则。
struct CaseInsensitiveCompare {
   
   
    bool operator()(const std::string& lhs, const std::string& rhs) const {
   
   
        return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end(),
            [](char a, char b){
   
    return tolower(a) < tolower(b); });
    }
};
std::map<std::string, int, CaseInsensitiveCompare> caseInsensitiveMap;
  • 内存管理mapset中的元素是按需分配的,删除元素不会立即释放内存,直到容器销毁或调用shrink_to_fit()。对于内存敏感的应用,需要注意适时释放不再使用的内存。

总结

mapset作为C++ STL中的重要成员,以其独特的键值存储和集合管理能力,在数据处理和算法实现中扮演着关键角色。正确理解和运用它们,可以显著提升代码的效率和清晰度。面对它们的潜在陷阱,如键的唯一性、性能考量以及迭代器的使用,采取合理的规避策略至关重要。通过实践和不断探索,你将能更加得心应手地驾驭这些强大的容器。

目录
相关文章
|
7天前
|
安全 程序员 C++
C++一分钟之-C++中的并发容器
【7月更文挑战第17天】C++11引入并发容器,如`std::shared_mutex`、`std::atomic`和线程安全的集合,以解决多线程中的数据竞争和死锁。常见问题包括原子操作的误用、锁的不当使用和迭代器失效。避免陷阱的关键在于正确使用原子操作、一致的锁管理以及处理迭代器失效。通过示例展示了如何安全地使用这些工具来提升并发编程的安全性和效率。
11 1
|
12天前
|
C++ 容器
【C++】map和set封装
【C++】map和set封装
14 2
|
12天前
|
存储 C++ 容器
【C++】map和set深度讲解(下)
【C++】map和set深度讲解(下)
23 2
|
12天前
|
存储 自然语言处理 Java
【C++】map和set深度讲解(上)
【C++】map和set深度讲解(上)
18 2
|
12天前
|
存储 C++ 容器
【C++】开散列实现unordered_map与unordered_set的封装
【C++】开散列实现unordered_map与unordered_set的封装
17 0
|
18天前
|
存储 算法 C++
【C++高阶】探索STL的瑰宝 map与set:高效数据结构的奥秘与技巧
【C++高阶】探索STL的瑰宝 map与set:高效数据结构的奥秘与技巧
27 0
|
12天前
|
设计模式 安全 编译器
【C++11】特殊类设计
【C++11】特殊类设计
32 10
|
17天前
|
C++
C++友元函数和友元类的使用
C++中的友元(friend)是一种机制,允许类或函数访问其他类的私有成员,以实现数据共享或特殊功能。友元分为两类:类友元和函数友元。类友元允许一个类访问另一个类的私有数据,而函数友元是非成员函数,可以直接访问类的私有成员。虽然提供了便利,但友元破坏了封装性,应谨慎使用。
45 9
|
12天前
|
存储 编译器 C语言
【C++基础 】类和对象(上)
【C++基础 】类和对象(上)
|
20天前
|
编译器 C++
【C++】string类的使用④(字符串操作String operations )
这篇博客探讨了C++ STL中`std::string`的几个关键操作,如`c_str()`和`data()`,它们分别返回指向字符串的const char*指针,前者保证以&#39;\0&#39;结尾,后者不保证。`get_allocator()`返回内存分配器,通常不直接使用。`copy()`函数用于将字符串部分复制到字符数组,不添加&#39;\0&#39;。`find()`和`rfind()`用于向前和向后搜索子串或字符。`npos`是string类中的一个常量,表示找不到匹配项时的返回值。博客通过实例展示了这些函数的用法。