【C++篇】在秩序与混沌的交响乐中: STL之map容器的哲学探寻

文章目录

  • C++ `map` 容器详解:高效存储与快速查找
    • 前言
    • 第一章:C++ `map` 的概念
      • 1.1 `map` 的定义
      • 1.2 `map` 的特点
    • 第二章:`map` 的构造方法
      • 2.1 常见构造函数
        • 2.1.1 示例:不同构造方法
      • 2.2 相关文档
    • 第三章:`map` 的常用操作
      • 3.1 插入操作详解
        • 3.1.1 使用 `insert()` 插入元素
        • 3.1.2 使用 `emplace()` 插入元素
        • 3.1.3 使用 `operator[]` 插入元素
      • 3.2 查找操作详解
        • 3.2.1 使用 `find()` 查找元素
        • 3.2.2 使用 `operator[]` 访问元素
      • 3.3 删除操作详解
        • 3.3.1 使用 `erase()` 删除元素
        • 3.3.2 清空 `map`
    • 第四章:`map` 的常用成员函数
      • 4.1 常用成员函数概述
      • 4.2 成员函数示例
    • 第五章:性能分析
      • 5.1 时间复杂度
      • 5.2 空间复杂度
    • 第六章:高级用法
      • 6.1 自定义排序和比较器
        • 6.1.1 示例:自定义比较器
      • 6.2 使用迭代器进行复杂操作
        • 6.2.1 示例:使用迭代器删除偶数键的元素
    • 第七章:`multimap` 的使用
      • 7.1 `multimap` 与 `map` 的区别
      • 7.2 使用 `multimap` 存储重复键
        • 7.2.1 示例:使用 `multimap` 存储重复键
      • 7.3 `multimap` 的操作
      • 7.4 使用场景
    • 总结

C++ map 容器详解:高效存储与快速查找

💬 欢迎讨论:在学习过程中,如果有任何疑问或想法,欢迎在评论区留言一起讨论。

👍 点赞、收藏与分享:觉得这篇文章对你有帮助吗?记得点赞、收藏并分享给更多的朋友吧!你们的支持是我不断进步的动力!
🚀 分享给更多人:如果你觉得这篇文章对你有帮助,欢迎分享给更多对 C++ 感兴趣的朋友,一起学习进步!


前言

C++ 标准模板库(STL)中的 map 容器是一种基于红黑树实现的关联容器,它允许用户以键值对的形式高效地存储和检索数据。 map 提供了高效的查找、插入和删除操作,并且所有元素都是根据键的顺序自动排列。由于其结构特点,map 的时间复杂度在查找、插入和删除操作上通常为 O(log N)。

本文将深入探讨 map 容器的概念、特性、性能分析及其基本操作,通过详细的示例和解释,帮助读者理解如何构建和使用这一重要数据结构。


第一章:C++ map 的概念

1.1 map 的定义

map 是 C++ STL 中的一种关联容器,存储的是键值对(key-value pairs)。其主要特性包括:

  • 唯一性:每个键在 map 中是唯一的,不能重复。如果插入相同的键,新值会替代旧值。
  • 自动排序map 会根据键的大小自动排序,默认使用 operator< 进行比较。
  • 底层实现map 通常使用红黑树实现,确保操作的时间复杂度保持在 O(log N)。

1.2 map 的特点

  • 快速查找:由于红黑树的结构特性,查找操作的时间复杂度为 O(log N)。
  • 动态数据支持:支持动态插入和删除数据,适合处理频繁变化的数据集。
  • 有序性:通过中序遍历,可以得到一个升序的序列,这对于某些算法(如排序)非常有用。

第二章:map 的构造方法

2.1 常见构造函数

map 提供了多种构造函数,允许用户根据不同需求初始化容器。以下是常见的构造函数:

构造函数功能
map()构造一个空的 map
map(size_type n, const T& val)构造一个包含 n 个值为 val 的元素的 map
map(const map& x)拷贝构造函数,构造与 x 相同的 map
map(InputIterator first, InputIterator last)使用 [first, last) 区间内的元素构造 map
map(std::initializer_list<value_type> init)使用初始化列表构造 map
2.1.1 示例:不同构造方法
#include <iostream>
#include <map>
using namespace std;

int main() {
    map<int, string> myMap;  // 空 map
    map<int, string> myMap2 = {{1, "One"}, {2, "Two"}}; // 初始化列表
    map<int, string> myMap3(myMap2); // 拷贝构造

    for (const auto& pair : myMap3) {
        cout << pair.first << ": " << pair.second << endl; // 输出: 1: One, 2: Two
    }
    return 0;
}
  • 解释
    • myMap 是一个空的 map
    • myMap2 使用初始化列表构造,直接插入键值对。
    • myMap3myMap2 的拷贝。

2.2 相关文档

  • C++ Reference: map constructor

第三章:map 的常用操作

3.1 插入操作详解

插入操作是 map 的基本操作之一。map 提供了多种插入元素的方法:

3.1.1 使用 insert() 插入元素

insert() 方法可以用来插入一个新的键值对。

#include <iostream>
#include <map>
using namespace std;

int main() {
    map<int, string> myMap;
    myMap.insert({1, "One"}); // 使用 insert 插入
    myMap.insert(make_pair(2, "Two")); // 另一种插入方式

    for (const auto& pair : myMap) {
        cout << pair.first << ": " << pair.second << endl; // 输出: 1: One, 2: Two
    }
    return 0;
}
  • 解释
    • insert() 可以通过 {} 初始化键值对,也可以使用 make_pair
3.1.2 使用 emplace() 插入元素

emplace() 方法允许在 map 中直接构造元素,避免不必要的复制。

#include <iostream>
#include <map>
using namespace std;

int main() {
    map<int, string> myMap;
    myMap.emplace(3, "Three"); // 使用 emplace 插入

    for (const auto& pair : myMap) {
        cout << pair.first << ": " << pair.second << endl; // 输出: 3: Three
    }
    return 0;
}
  • 解释
    • emplace() 直接在 map 中构造元素,相比 insert() 更加高效,尤其是在处理复杂对象时。
3.1.3 使用 operator[] 插入元素

通过 operator[] 可以直接插入或修改元素。如果键不存在,则会插入一个默认值。

#include <iostream>
#include <map>
using namespace std;

int main() {
    map<int, string> myMap;

    myMap[1] = "One"; // 插入键为 1 的元素
    myMap[2] = "Two"; // 插入键为 2 的元素

    for (const auto& pair : myMap) {
        cout << pair.first << ": " << pair.second << endl; // 输出: 1: One, 2: Two
    }
    return 0;
}
  • 解释
    • 使用 operator[] 插入时,如果键已存在,则会更新其值。

3.2 查找操作详解

查找操作使我们能够确认一个键是否存在于 map 中。主要方法有:

3.2.1 使用 find() 查找元素

find() 方法返回一个迭代器,指向指定键的元素。

#include <iostream>
#include <map>
using namespace std;

int main() {
    map<int, string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}};

    auto it = myMap.find(2);
    if (it != myMap.end()) {
        cout << "Found: " << it->second << endl; // 输出: Found: Two
    } else {
        cout << "Not found" << endl;
    }

    return 0;
}
  • 解释
    • 如果找到键,find() 返回指向该元素的迭代器;否则返回 end() 迭代器。
3.2.2 使用 operator[] 访问元素

通过 operator[] 可以直接访问值,如果键不存在,则会插入一个默认值。

#include <iostream>
#include <



map>
using namespace std;

int main() {
    map<int, string> myMap = {{1, "One"}, {2, "Two"}};

    cout << "Element at key 1: " << myMap[1] << endl; // 输出: Element at key 1: One
    cout << "Element at key 3: " << myMap[3] << endl; // 会插入键为 3 的元素并返回默认值

    return 0;
}
  • 解释
    • 如果访问一个不存在的键,operator[] 会插入一个键为该值的元素。

3.3 删除操作详解

删除操作使我们能够从 map 中移除特定的元素。常用的方法有:

3.3.1 使用 erase() 删除元素

erase() 方法可以根据键或迭代器删除元素。

#include <iostream>
#include <map>
using namespace std;

int main() {
    map<int, string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}};

    myMap.erase(2); // 删除键为 2 的元素

    for (const auto& pair : myMap) {
        cout << pair.first << ": " << pair.second << endl; // 输出: 1: One, 3: Three
    }

    return 0;
}
  • 解释
    • erase() 可以直接通过键删除元素,也可以通过迭代器删除。
3.3.2 清空 map

使用 clear() 方法可以清空整个 map

#include <iostream>
#include <map>
using namespace std;

int main() {
    map<int, string> myMap = {{1, "One"}, {2, "Two"}};

    myMap.clear(); // 清空 map

    cout << "Size after clear: " << myMap.size() << endl; // 输出: Size after clear: 0

    return 0;
}
  • 解释
    • clear() 方法会删除 map 中的所有元素,使其大小变为 0。

第四章:map 的常用成员函数

4.1 常用成员函数概述

成员函数功能
begin()返回指向第一个元素的迭代器
end()返回指向超出最后一个元素的迭代器
size()返回元素个数
empty()判断 map 是否为空
clear()清空 map 中所有元素

4.2 成员函数示例

#include <iostream>
#include <map>
using namespace std;

int main() {
    map<int, string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}};

    cout << "Size: " << myMap.size() << endl; // 输出: Size: 3
    cout << "Is empty: " << (myMap.empty() ? "Yes" : "No") << endl; // 输出: Is empty: No

    for (auto it = myMap.begin(); it != myMap.end(); ++it) {
        cout << it->first << ": " << it->second << endl; // 输出: 1: One, 2: Two, 3: Three
    }

    return 0;
}
  • 解释
    • 示例中展示了如何使用 size()empty()begin()end() 函数。

第五章:性能分析

5.1 时间复杂度

map 的主要操作时间复杂度分析如下:

  • 查找:O(log N)
  • 插入:O(log N)
  • 删除:O(log N)

5.2 空间复杂度

map 的空间复杂度主要取决于存储的元素个数,空间复杂度为 O(N),此外还需要额外的存储空间用于维护红黑树的平衡。


第六章:高级用法

6.1 自定义排序和比较器

在 C++ 中,map 默认使用 operator< 进行键的排序,但我们可以自定义比较器来实现不同的排序规则。例如,可以使用自定义结构体或函数来定义键的比较方式。

6.1.1 示例:自定义比较器
#include <iostream>
#include <map>
using namespace std;

struct CustomCompare {
    bool operator()(const int& a, const int& b) const {
        return a > b; // 逆序排序
    }
};

int main() {
    map<int, string, CustomCompare> myMap;
    myMap[1] = "One";
    myMap[2] = "Two";
    myMap[3] = "Three";

    for (const auto& pair : myMap) {
        cout << pair.first << ": " << pair.second << endl; // 输出: 3: Three, 2: Two, 1: One
    }

    return 0;
}
  • 解释
    • 在这个示例中,CustomCompare 结构体定义了一个逆序排序的比较器,从而改变了 map 中元素的排序方式。

6.2 使用迭代器进行复杂操作

map 的迭代器可以用来遍历元素,进行更复杂的操作,例如条件删除或元素修改。

6.2.1 示例:使用迭代器删除偶数键的元素
#include <iostream>
#include <map>
using namespace std;

int main() {
    map<int, string> myMap = {{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}};

    for (auto it = myMap.begin(); it != myMap.end(); ) {
        if (it->first % 2 == 0) {
            it = myMap.erase(it); // 删除偶数键的元素
        } else {
            ++it; // 只在未删除元素时移动迭代器
        }
    }

    for (const auto& pair : myMap) {
        cout << pair.first << ": " << pair.second << endl; // 输出: 1: One, 3: Three
    }

    return 0;
}
  • 解释
    • 使用迭代器的 erase() 方法删除元素时,要注意更新迭代器,否则会导致迭代器失效。

第七章:multimap 的使用

multimap 是 STL 中的另一种关联容器,与 map 类似,但允许键重复。适用于需要存储多个相同键的场景。

7.1 multimapmap 的区别

特性mapmultimap
键的唯一性每个键是唯一的,不允许重复允许多个相同键的存在
值的替代性插入重复键时替代旧值插入重复键时保留所有值
查找操作使用 find() 查找特定键使用 equal_range() 查找所有值
使用场景用于需要唯一键的情况,如字典用于需要存储多个值的情况,如记录成绩
迭代器迭代器按键的升序遍历迭代器按键的升序遍历
性能查找、插入、删除操作 O(log N)查找、插入、删除操作 O(log N)

7.2 使用 multimap 存储重复键

7.2.1 示例:使用 multimap 存储重复键
#include <iostream>
#include <map>
using namespace std;

int main() {
    multimap<int, string> myMultiMap;

    myMultiMap.insert({1, "One"});
    myMultiMap.insert({1, "Another One"});
    myMultiMap.insert({2, "Two"});
    myMultiMap.insert({3, "Three"});
    myMultiMap.insert({3, "Another Three"});

    for (const auto& pair : myMultiMap) {
        cout << pair.first << ": " << pair.second << endl;
        // 输出: 
        // 1: One
        // 1: Another One
        // 2: Two
        // 3: Three
        // 3: Another Three
    }

    return 0;
}
  • 解释
    • 在这个示例中,multimap 允许多个相同的键(如 1 和 3)存储多个值。每个键都可以关联多个不同的值,并保持插入的顺序。

7.3 multimap 的操作

  • 插入:可以使用 insert() 方法向 multimap 中添加元素,允许重复键。

    myMultiMap.insert({key, value});
    
  • 查找:使用 equal_range() 方法可以查找某个键对应的所有值。

    auto range = myMultiMap.equal_range(key);
    for (auto it = range.first; it != range.second; ++it) {
        cout << it->second << endl; // 输出所有与键对应的值
    }
    
  • 删除:可以使用 erase() 方法删除特定的键或元素,但要注意,删除某个键会删除所有该键的元素。

myMultiMap.erase(key); // 删除所有键为 key 的元素

7.4 使用场景

  • 重复记录:适合用于存储相同键但不同值的数据,例如,存储学生的多个成绩、顾客的订单等。
  • 统计信息:在需要对某些值进行频率统计时,可以使用 multimap 来记录所有相同键的值。
  • 分类存储:当需要将数据分组时,可以使用 multimap 来关联相同类别的多个值。

总结

C++ 的 map 容器不仅仅是一个高效的键值对存储工具,它更是一门在数据结构中交织秩序与自由的艺术。map 容器通过红黑树的稳定性与自动排序的特性,实现了在 O(log N) 时间内的快速查找、插入和删除,这使其在需要高效数据管理的场景中得以广泛应用。本文从基础构造到高级特性,逐步解剖了 map 的各项功能,探讨了其在日常开发和算法竞赛中的使用策略。自定义比较器、迭代器操作、多键存储等进阶用法,展示了 map 的灵活性与深度,赋予开发者在复杂数据处理中优雅应对的力量。希望通过本文,读者能够更加熟练地掌握 map 容器,让代码在数据的交响乐中游刃有余。


以上就是关于【C++篇】在秩序与混沌的交响乐中: STL之map容器的哲学探寻的内容啦,各位大佬有什么问题欢迎在评论区指正,或者私信我也是可以的啦,您的支持是我创作的最大动力!❤️

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/912637.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Redis缓存机制实现高并发接口调试

创建接口 这里使用的是阿里云提供的接口服务直接做的测试&#xff0c;接口地址 curl http://localhost:8080/initData?tokenAppWithRedis 这里主要通过参数cacheFirstfalse和true来区分是否走缓存&#xff0c;正常的业务机制可能是通过后台代码逻辑自行控制的&#xff0c;这…

STM32ZET6-USART使用

一、原理说明 STM32自带通讯接口 通讯目的 通信方式&#xff1a; 全双工&#xff1a;通信时可以双方同时通信。 半双工&#xff1a;通信时同一时间只能一个设备发送数据&#xff0c;其他设备接收。 单工&#xff1a;只能一个设备发送到另一个设备&#xff0c;例如USART只有…

深度学习-张量相关

一. 张量的创建 张量简介 张量是pytorch的基本数据结构 张量&#xff0c;英文为Tensor&#xff0c;是机器学习的基本构建模块&#xff0c;是以数字方式表示数据的形式。 例如&#xff0c;图像可以表示为形状为 [3, 224, 224] 的张量&#xff0c;这意味着 [colour_channels, h…

图片表格文字模糊转电子版Excel的解决之道

在面对图片中的表格文字需要转化为电子版Excel或其它格式文本时&#xff0c;当前的主流方法是借助OCR&#xff08;光学字符识别&#xff09;技术。然而&#xff0c;OCR技术的识别效果深受成像质量&#xff0c;即图像文字的清晰度影响。图像越模糊&#xff0c;识别的难度越大&am…

LC:二分查找——杂记

文章目录 268. 丢失的数字162. 寻找峰值 268. 丢失的数字 LC将此题归类为二分查找&#xff0c;并且为简单题&#xff0c;下面记一下自己对这道题目的思考。 题目链接&#xff1a;268.丢失的数字 第一次看到这个题目&#xff0c;虽然标注的为简单&#xff0c;但肯定不能直接排…

增删改查基础项目总结

上篇中主要负责后端部分完成了一个简单的学习辅助系统部分界面&#xff0c;主要针对增删改查进行了练习&#xff0c;过程中遇到了一些细节上的问题以及当时做的时候去查阅的一些之前没有太注意到的额外知识&#xff0c;所以还需要进行进一步梳理&#xff0c;像登录校验的方法以…

YOLOv11融合[ECCV2024]自调制特征聚合SMFA模块及相关改进思路|YOLO改进最简教程

YOLOv11v10v8使用教程&#xff1a; YOLOv11入门到入土使用教程 YOLOv11改进汇总贴&#xff1a;YOLOv11及自研模型更新汇总 《SMFANet: A Lightweight Self-Modulation Feature Aggregation Network for Efficient Image Super-Resolution》 一、 模块介绍 论文链接&#xff1…

【51单片机】I2C总线详解 + AT24C02

学习使用的开发板&#xff1a;STC89C52RC/LE52RC 编程软件&#xff1a;Keil5 烧录软件&#xff1a;stc-isp 开发板实图&#xff1a; 文章目录 AT24C02介绍存储器 I2C总线介绍I2C时序结构数据帧AT24C02数据帧 编程实例 —— 按键控制数据大小&存储器写入读出 AT24C02介绍 …

Kafka 可观测性最佳实践

Kafka 概述 Kafka 是由 LinkedIn 开发一个分布式的基于发布订阅模式的消息队列&#xff0c;是一个实时数据处理系统&#xff0c;可以横向扩展。与 RabbitMQ、RockerMQ 等中间件一样拥有几大特点&#xff1a; 异步处理服务解耦流量削峰 监控 Kafka 是非常重要的&#xff0c;因…

智能制造基础- TPM(全面生产维护)

TPM 前言一、TPM二、TPM实施步骤三、 消除主要问题3.1 实施指南3.2 如何进行“主要问题”的消除&#xff1f; 四、自主维护4.1 实施指南4.2 主要工作内容4.3 如何进行“自主维护“ 五、计划维护5.1 实施指南5.2 如何实施计划维护 六、TPM 适当的 设备 设计5.1 实施指南5.2 如何…

数据库SQLite的使用

SQLite是一个C语言库&#xff0c;实现了一个小型、快速、独立、高可靠性、功能齐全的SQL数据库引擎。SQLite文件格式稳定、跨平台且向后兼容。SQLite源代码属于公共领域(public-domain)&#xff0c;任何人都可以免费将其用于任何目的。源码地址&#xff1a;https://github.com/…

openpyxl处理Excel模板,带格式拷贝行和数据填入

本文中用openpyxl操作Excell 模板,进行行拷贝和数据填充. 主要涉及单元格格式的拷贝,合并单元格的拷贝,行高和列宽的处理. 将模板表格分为三部分,头部,中间循环填充部分,尾部.模板参数中设置头部高度,循环部分高度,剩余为尾部. 拷贝时先拷贝填充头部 ,然后根据数据循环拷贝填…

【FPGA开发】AXI-Lite总线协议解读、Verilog逻辑开发与仿真、Alex Forencich代码解读

目录 AXI是什么AXI是如何工作的AXI-Lite定义AXI-Lite的关键特性AXI-Lite信号列表AXI-Lite信号时序时钟和复位握手机制写请求通道&#xff08;AW&#xff09;写数据通道&#xff08;W&#xff09;写响应通道&#xff08;B&#xff09;读请求通道&#xff08;AR&#xff09;读数据…

zabbix 7.0 安装(服务器、前端、代理等)

https://www.zabbix.com/download 使用上面的地址&#xff0c;按教程执行命令安装

uniapp—android原生插件开发(2原生插件开发)

本篇文章从实战角度出发&#xff0c;将UniApp集成新大陆PDA设备RFID的全过程分为四部曲&#xff0c;涵盖环境搭建、插件开发、AAR打包、项目引入和功能调试。通过这份教程&#xff0c;轻松应对安卓原生插件开发与打包需求&#xff01; ***环境问题移步至&#xff1a;uniapp—an…

【DCCMCI】多模态情感分析的层次去噪、表征解纠缠和双通道跨模态-上下文交互

abstract 多模态情感分析旨在从文本、声音和视觉数据等各种模态中提取情感线索&#xff0c;并对其进行操作&#xff0c;以确定数据中固有的情感极性。尽管在多模态情感分析方面取得了重大成就&#xff0c;但在处理模态表征中的噪声特征、消除模态表征之间情感信息的实质性差距…

【网络安全】线程安全分析及List遍历

未经许可,不得转载。 文章目录 线程线程安全问题遍历List的方式方式一方式二方式三方式四(Java 8)方式五(Java 8 Lambda)遍历List的同时操作ListVector是线程安全的?使用线程安全的CopyOnWriteArrayList使用线程安全的List.forEach线程 线程是程序执行的最小单位。一个程…

基于MFC实现的赛车游戏

一、问题描述 游戏背景为一环形车道图&#xff0c;选择菜单选项“开始游戏”则可开始游戏。游戏的任务是使用键盘上的方向键操纵赛道上的蓝色赛车追赶红色赛车&#xff0c;红色赛车沿车道顺时针行驶&#xff0c;出发点和终点均位于车道左上方。任一赛车先达到终点则比赛结束。…

SpringBoot赋能的共享汽车业务管理系统

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

「QT」几何数据类 之 QLineF 浮点型直线类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…