当前位置: 首页 > news >正文

C++笔记——STL map

map 是 C++ 标准模板库(STL)中一个非常重要的关联式容器,它提供了一种“键-值”对的存储和访问机制。

1. 核心概念与特性

  • 键值对map 存储的元素都是 std::pair<const Key, T> 类型的对象。简单理解,就是一个唯一的 Key(关键字)映射到一个 Value(值)。

  • 有序性map 中的元素会根据 键(Key) 自动进行排序。默认情况下,它使用 std::less<Key>(即 < 操作符)对键进行升序排序。你也可以通过自定义比较函数来指定排序规则。

  • 唯一性map 容器保证所有元素的键都是唯一的。如果你尝试插入一个已经存在的键,插入操作会失败。

  • 底层实现map 通常使用红黑树 实现。红黑树是一种自平衡的二叉搜索树,这使得 map 在插入、删除和查找操作上的时间复杂度都能保持在 O(log n),效率非常稳定。

  • 不可修改的键:一旦一个元素被插入到 map 中,它的键就是常量,不能被修改。这是为了不破坏红黑树的结构。但你可以修改该键对应的值。

2. 基本用法

头文件与声明

cpp

#include <iostream>
#include <map> // 必须包含的头文件
#include <string>int main() {// 声明一个 map,键为 string,值为 intstd::map<std::string, int> studentScores;// 也可以声明时指定自定义比较规则(例如降序)// std::map<std::string, int, std::greater<std::string>> studentScoresDesc;return 0;
}
常用操作
插入元素

有几种常见的方法:

  1. 使用 insert 成员函数

    cpp

    std::map<std::string, int> studentScores;// 方法1:使用 make_pair
    studentScores.insert(std::make_pair("Alice", 95));
    // 方法2:使用花括号 {} (C++11)
    studentScores.insert({"Bob", 88});
    // 方法3:使用 pair 的构造函数
    studentScores.insert(std::pair<const std::string, int>("Charlie", 70));// insert 会返回一个 pair<iterator, bool>
    auto ret = studentScores.insert({"Alice", 100}); // 键 "Alice" 已存在,插入失败
    if (!ret.second) {std::cout << "Insertion failed. Key 'Alice' already exists.\n";
    }
  2. 使用 operator[](最常用、最直观)

    cpp

    std::map<std::string, int> studentScores;studentScores["Alice"] = 95; // 如果 "Alice" 不存在,会先创建一个并赋值
    studentScores["Bob"] = 88;
    studentScores["Alice"] = 100; // 因为 "Alice" 已存在,这会修改其对应的值std::cout << studentScores["Alice"]; // 输出 100

    注意operator[] 如果找不到键,会自动插入一个具有该键的新元素,并用值类型的默认构造函数初始化其值(对于 int 是 0)。这有时会导致非预期的插入。

访问元素
  1. 使用 operator[]

    cpp

    int score = studentScores["Alice"]; // 如果 "Alice" 不存在,会插入一个新元素!
  2. 使用 at 成员函数 (C++11)

    cpp

    int score = studentScores.at("Alice"); // 如果 "Alice" 不存在,会抛出 std::out_of_range 异常

    推荐在确定键存在时使用 at,因为它更安全,不会意外插入新元素。

  3. 使用迭代器

    cpp

    auto it = studentScores.find("Alice");
    if (it != studentScores.end()) {// it->first 是键 ("Alice")// it->second 是值 (100)std::cout << it->first << ": " << it->second << std::endl;
    } else {std::cout << "Key not found.\n";
    }
查找元素

使用 find 成员函数,它返回一个迭代器。

cpp

std::map<std::string, int>::iterator it = studentScores.find("Bob");
// 或者用 auto
auto it = studentScores.find("Bob");if (it != studentScores.end()) {std::cout << "Found: " << it->first << " -> " << it->second << std::endl;
} else {std::cout << "Key 'Bob' not found." << std::endl;
}

注意:不要使用 std::find 算法来查找 map 的元素,因为它是线性搜索,效率远低于 map 自己的 find 方法(O(n) vs O(log n))。

删除元素

使用 erase 成员函数。

cpp

std::map<std::string, int> studentScores = {{"Alice", 95}, {"Bob", 88}, {"Charlie", 70}};// 方法1:通过迭代器删除
auto it = studentScores.find("Bob");
if (it != studentScores.end()) {studentScores.erase(it);
}// 方法2:通过键删除
size_t numRemoved = studentScores.erase("Charlie"); // 返回被删除元素的个数(对于map是0或1)// 方法3:删除一个范围
studentScores.erase(studentScores.begin(), studentScores.find("Alice")); // 删除 "Alice" 之前的所有元素
遍历元素

由于 map 是有序的,遍历时会按照键的顺序进行。

cpp

std::map<std::string, int> studentScores = {{"Alice", 95}, {"Bob", 88}, {"Charlie", 70}};// 方法1:使用迭代器
for (std::map<std::string, int>::iterator it = studentScores.begin(); it != studentScores.end(); ++it) {std::cout << it->first << ": " << it->second << std::endl;
}// 方法2:使用基于范围的for循环 (C++11) - 推荐!
for (const auto& pair : studentScores) {std::cout << pair.first << ": " << pair.second << std::endl;
}// 输出:
// Alice: 95
// Bob: 88
// Charlie: 70

3. 复杂度分析

  • 插入O(log n)

  • 查找O(log n)

  • 删除O(log n)

  • 遍历O(n)

4. 与其他容器的比较

特性std::mapstd::unordered_mapstd::multimap
有序性有序(按键排序)无序有序(按键排序)
底层结构红黑树(平衡BST)哈希表红黑树(平衡BST)
查找复杂度O(log n)平均 O(1),最坏 O(n)O(log n)
键的唯一性键唯一键唯一键可重复
需要哈希函数
需要比较函数
使用场景需要元素有序需要极速查找,不关心顺序需要有序且键可重复

5. 高级用法与技巧

自定义比较函数

当键是自定义类型或需要特殊排序规则时使用。

cpp

struct Student {std::string name;int id;
};// 自定义比较函数对象
struct CompareByID {bool operator()(const Student& a, const Student& b) const {return a.id < b.id; // 按 ID 升序排列}
};int main() {std::map<Student, int, CompareByID> studentScores;studentScores[{"Alice", 2}] = 90;studentScores[{"Bob", 1}] = 85;studentScores[{"Charlie", 3}] = 95;// 遍历时,会按 ID 1(Bob), 2(Alice), 3(Charlie) 的顺序输出for (const auto& pair : studentScores) {std::cout << "ID: " << pair.first.id << ", Name: " << pair.first.name << ", Score: " << pair.second << std::endl;}return 0;
}
emplace 高效构造 (C++11)

emplace 可以直接在容器内部构造元素,避免了临时对象的创建和拷贝/移动。

cpp

std::map<std::string, int> studentScores;
studentScores.emplace("David", 92); // 直接在 map 中构造 pair("David", 92)

总结

std::map 是一个强大且灵活的有序关联容器,它通过键值对的形式存储数据,并保证键的唯一性和有序性。其基于红黑树的实现提供了稳定的对数时间复杂度操作。在选择使用 map 时,需要考虑:

  • 你是否需要元素有序

  • 你的键是否是唯一的?

  • 你的应用场景是否能接受 O(log n) 的查找时间?

如果不需要有序,且追求极致的查找速度,可以考虑 std::unordered_map。如果需要键可以重复,则考虑 std::multimap

http://www.dtcms.com/a/587128.html

相关文章:

  • 电商运营是销售吗威海seo网站推广
  • 在网站制作完成后网站建设网站开发都需要哪些图
  • python - day 13
  • 响应式网站源码.net网络营销的认知
  • 玉林网站制作wordpress google open sans
  • 个人网站建设 免费下载wordpress首页登录
  • 免费网站建设seo精通网站建设电子档
  • 网络seo营销推广成都seo培
  • 服务器网站后台登陆密码黄框显示福永网站建设
  • C++ LeetCode 力扣刷题 344. 反转字符串
  • 抄写diffcloth的源码
  • 龙华建设局网站深圳网站做优化哪家公司好
  • 网站开发php 图片上传失败媒体网站
  • 亿玫网站建设徐州企业建站模板
  • 哪里网站建设公司比较好英德市住房和城乡建设局网站
  • 温州网站开发南通seo网站排名优化
  • 窄带无线信道
  • 郑州直播网站建设公司哪个网站可以免费做招牌
  • 模态框的两种管理思路
  • 正规网站建设哪家好怎样申请网站呢
  • 测试用例~
  • 怎么做培训班网站找商务合作的平台
  • 做卖车网站需要什么手续费为什么招聘网站不能用自己做的简历
  • 昆山网站建设网站宝安网站设计公司
  • 中国可信网站查询丹东市做网站
  • 五大智能锁PK:哪种最适合你家?
  • 怎么用自己的电脑做网站空间电商运营培训课程
  • 江门网站开发多少钱企业备案网站服务内容
  • 北京建设信源咨询有限公司网站杭州发布最新消息
  • 坪山网站建设服务建设摩托车官网报价