C++怎么使用std::multimap允许重复键的映射

来源:Golang编程网作者:小团团头衔:草根站长
导读:本期聚焦于小伙伴创作的《C++怎么使用std::multimap允许重复键的映射》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++怎么使用std::multimap允许重复键的映射》有用,将其分享出去将是对创作者最好的鼓励。

在C++标准模板库中,std::multimap是一种关联式容器,它允许同一个键对应多个不同的元素,和std::map的核心区别在于键的唯一性限制被放开,同时所有元素会按照键的大小自动排序,底层通过红黑树实现,插入、查找、删除操作的时间复杂度都是对数级别。

C++怎么使用std::multimap允许重复键的映射

std::multimap的基本定义与初始化

要使用std::multimap,首先需要包含头文件<map>,它的模板参数有两个,第一个是键的类型,第二个是对应值的类型,也可以额外指定排序规则,默认按照键的升序排列。

以下是几种常见的定义和初始化方式:

#include <map>
#include <string>
#include <iostream>

int main() {
    // 1. 定义空的std::multimap,键为int类型,值为string类型
    std::multimap<int, std::string> mmap1;

    // 2. 通过初始化列表初始化,允许重复键
    std::multimap<int, std::string> mmap2 = {
        {1, "apple"},
        {1, "banana"}, // 键1重复
        {2, "cherry"},
        {1, "date"}    // 键1再次重复
    };

    // 3. 自定义排序规则,按照键的降序排列
    std::multimap<int, std::string, std::greater<int>> mmap3;
    return 0;
}

元素插入操作

std::multimap插入元素的方式和std::map类似,但是不需要判断键是否已经存在,因为允许重复键,所以每次插入都会新增元素。常用的插入方法有insert成员函数和emplace成员函数。

#include <map>
#include <string>
#include <iostream>

int main() {
    std::multimap<int, std::string> mmap;

    // 使用insert插入键值对,参数为pair对象
    mmap.insert(std::pair<int, std::string>(1, "first"));
    // 也可以使用make_pair简化写法
    mmap.insert(std::make_pair(1, "second"));
    // 直接传递两个参数构造pair
    mmap.insert({2, "third"});

    // 使用emplace直接构造元素,效率更高
    mmap.emplace(2, "fourth");
    mmap.emplace(1, "fifth");

    // 输出所有元素验证插入结果
    for (auto &item : mmap) {
        std::cout << item.first << " : " << item.second << std::endl;
    }
    // 输出结果会按键升序排列,键1对应三个值,键2对应两个值
    return 0;
}

查找指定键的所有元素

由于std::multimap允许重复键,所以无法通过find函数获取某个键对应的所有元素,find只会返回第一个匹配键的迭代器。要获取某个键对应的所有值,需要使用lower_boundupper_bound函数,或者equal_range函数。

使用lower_bound和upper_bound

lower_bound(key)返回第一个键大于等于key的迭代器,upper_bound(key)返回第一个键大于key的迭代器,两者的区间就是所有键等于key的元素范围。

#include <map>
#include <string>
#include <iostream>

int main() {
    std::multimap<int, std::string> mmap = {
        {1, "a"}, {1, "b"}, {2, "c"}, {1, "d"}, {3, "e"}
    };

    int target_key = 1;
    auto it_low = mmap.lower_bound(target_key);
    auto it_up = mmap.upper_bound(target_key);

    std::cout << "键" << target_key << "对应的所有值:" << std::endl;
    for (auto it = it_low; it != it_up; ++it) {
        std::cout << it->second << std::endl;
    }
    // 输出结果:a b d
    return 0;
}

使用equal_range

equal_range(key)会直接返回一个pair,first是lower_bound的结果,second是upper_bound的结果,使用起来更简洁。

#include <map>
#include <string>
#include <iostream>

int main() {
    std::multimap<int, std::string> mmap = {
        {1, "a"}, {1, "b"}, {2, "c"}, {1, "d"}, {3, "e"}
    };

    int target_key = 2;
    auto range = mmap.equal_range(target_key);

    std::cout << "键" << target_key << "对应的所有值:" << std::endl;
    for (auto it = range.first; it != range.second; ++it) {
        std::cout << it->second << std::endl;
    }
    // 输出结果:c
    return 0;
}

遍历容器元素

std::multimap的遍历方式和普通容器一致,可以使用迭代器遍历、范围for循环遍历,也可以使用for_each算法遍历。

#include <map>
#include <string>
#include <iostream>
#include <algorithm>

int main() {
    std::multimap<int, std::string> mmap = {
        {1, "x"}, {2, "y"}, {1, "z"}
    };

    // 1. 迭代器遍历
    std::cout << "迭代器遍历结果:" << std::endl;
    for (auto it = mmap.begin(); it != mmap.end(); ++it) {
        std::cout << it->first << " : " << it->second << std::endl;
    }

    // 2. 范围for循环遍历
    std::cout << "范围for遍历结果:" << std::endl;
    for (auto &item : mmap) {
        std::cout << item.first << " : " << item.second << std::endl;
    }

    // 3. for_each算法遍历
    std::cout << "for_each遍历结果:" << std::endl;
    std::for_each(mmap.begin(), mmap.end(), [](const auto &item) {
        std::cout << item.first << " : " << item.second << std::endl;
    });
    return 0;
}

删除元素操作

std::multimap提供了多种删除元素的方式,包括通过迭代器删除单个元素、通过键删除所有对应元素、通过迭代器区间删除元素。

#include <map>
#include <string>
#include <iostream>

int main() {
    std::multimap<int, std::string> mmap = {
        {1, "a"}, {1, "b"}, {2, "c"}, {1, "d"}, {3, "e"}
    };

    // 1. 删除第一个键为1的元素(通过find获取第一个迭代器)
    auto it = mmap.find(1);
    if (it != mmap.end()) {
        mmap.erase(it);
    }

    // 2. 删除所有键为1的元素,返回删除的元素个数
    size_t del_count = mmap.erase(1);
    std::cout << "删除了" << del_count << "个键为1的元素" << std::endl;

    // 3. 删除迭代器区间内的元素,这里删除所有剩余元素
    mmap.erase(mmap.begin(), mmap.end());

    std::cout << "删除后容器大小:" << mmap.size() << std::endl;
    return 0;
}

std::multimap与std::map的核心差异

两者都是标准库的关联容器,底层都是红黑树实现,主要差异如下:

对比项std::mapstd::multimap
键唯一性键唯一,不允许重复键可以重复,允许同一个键对应多个值
operator[]支持支持,可通过键直接访问或修改值不支持,因为无法确定唯一对应的值
insert返回值返回pair,包含迭代器和是否插入成功的bool值只返回插入元素的迭代器
适用场景键值一一对应的场景一个键对应多个值的场景,比如学生ID对应多门课程成绩

实际开发注意事项

  • std::multimap不允许使用operator[]访问元素,因为存在重复键,无法确定返回哪一个值,访问元素需要通过迭代器或者find系列函数。
  • 插入元素时不会因为键重复而覆盖原有元素,所有重复键的元素都会被保留,按插入顺序在键的区间内排列。
  • 如果需要无序存储、允许重复键的映射,可以考虑使用std::unordered_multimap,底层基于哈希表实现,平均查找时间复杂度是O(1),但是元素不会自动排序。
  • 遍历的时候如果修改元素的值不会影响排序,但是如果修改元素的键会破坏容器的内部结构,导致未定义行为,所以不要直接修改迭代器指向的键。
总结来说,当遇到需要存储键值对且允许键重复的场景时,std::multimap是非常合适的选择,掌握它的插入、查找、遍历、删除操作,就能应对大部分相关的开发需求。

std::multimapC++multimap用法重复键映射修改时间:2026-06-29 08:03:49

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。