Map和MultiMap使用

本文通过C++代码示例介绍了标准模板库中Map和MultiMap的使用方法,包括元素的插入、查找及遍历等操作。

#pragma once

class TestMap
{
public:
 TestMap(void);
 virtual ~TestMap(void);
 void test();
 void test1();
};


class TestMultiMap
{
public:
 TestMultiMap(void);
 virtual ~TestMultiMap(void);
 void test();
};

//---------------------------------------------------------

 

#include "TestMap_TestMultiMap.h"
#include <map>
#include <iostream>
#include <string>

using namespace std;


TestMap::TestMap(void)
{
}

TestMap::~TestMap(void)
{
}

void TestMap::test()
{
 map<int,string> coll;
 coll.insert(make_pair(5,"tagged"));
 coll.insert(make_pair(2,"a"));
 coll.insert(make_pair(1,"this"));
 coll.insert(make_pair(4,"of"));
 coll.insert(make_pair(6,"strings"));
 std::pair<map<int, string>::iterator, bool> retInsert;  //------------------- 判断插入结果
 retInsert = coll.insert(make_pair(1,"is"));
 if( !retInsert.second)
  cout<<"Failed in insert (1,\"is\")\n";
 coll.insert(make_pair(3,"multimap"));
 map<int,string>::const_iterator pos;
 for( pos = coll.begin(); pos != coll.end(); ++pos)
 {
  cout<<pos->second<<' ';
 }
 cout<<endl;
}

void TestMap::test1()
{
 map<string,float> coll;
 coll["VAT"] = 0.15;
 coll["Pi"] = 3.14159;
 coll["an arbitrary number"] = 4983.223;
 coll["NULL"] = 0;


 map<string,float>::const_iterator pos;
 for( pos = coll.begin(); pos != coll.end(); ++pos)
 {
  cout<<"("<<pos->first<<","<<pos->second<<") ";
 }
 cout<<endl;
}


TestMultiMap::TestMultiMap(void)
{
}

TestMultiMap::~TestMultiMap(void)
{
}

void TestMultiMap::test()
{
 multimap<int,string> coll;
 coll.insert(make_pair(5,"tagged"));
 coll.insert(make_pair(2,"a"));
 coll.insert(make_pair(1,"this"));
 coll.insert(make_pair(4,"of"));
 coll.insert(make_pair(6,"strings"));
 coll.insert(make_pair(1,"is"));
 coll.insert(make_pair(3,"multimap"));
 multimap<int,string>::const_iterator pos;
 for( pos = coll.begin(); pos != coll.end(); ++pos)
 {
  cout<<pos->second<<' ';
 }
 cout<<endl;
}

 

<think>好的,我现在需要帮助用户理解C++标准库中mapmultimap的区别及使用场景。用户之前已经提问过关于multimapmultiset的区别,现在想更深入地比较mapmultimap。根据用户提供的引用内容,我需要综合这些信息,并确保回答结构清晰,符合用户的要求。 首先,回顾用户之前的问题我的回答,已经讨论了multimapmultiset的底层实现都是红黑树,允许重复元素,而mapset不允许。现在用户的问题更聚焦于mapmultimap之间的比较,因此需要详细说明这两者的区别。 接下来,查看用户提供的引用内容。引用[3]明确指出mapmultimap的主要区别在于是否允许重复的键。引用[1][2]中的代码示例展示了multimap在处理相同键时的应用场景,比如统计单词频率并按频率排序,同时保留相同频率的单词。引用[5]的代码示例显示了multimap如何存储多个相同优先级的任务。引用[4]讨论了map与hash_map的区别,但用户的问题不涉及hash_map,所以可能暂时忽略这部分。 需要整理出以下几个方面的对比: 1. **键的唯一性**:map的键必须唯一,multimap允许重复键。 2. **数据结构**:两者都基于红黑树,保持有序。 3. **操作差异**:插入元素时,mapinsert可能失败(如果键已存在),而multimap总是成功。访问元素时,map可以通过operator[]访问值,而multimap需要范围查询。 4. **使用场景**:map适合需要唯一键且快速查找的情况,如配置项;multimap适合需要多个相同键的情况,如事件调度、频率统计。 然后需要确保回答符合用户给出的格式要求,包括使用中文、行内公式用$...$,独立公式用$$...$$,但这里可能不需要数学公式。同时,要生成相关问题,并在引用处添加标识符。 需要注意用户之前的回答中提到的红黑树实现性能分析,这里可以再次提及,但重点放在mapmultimap的比较上。此外,用户提供的代码示例可以用于用法示例部分,以展示具体差异。 最后,生成的相关问题需要围绕mapmultimap的底层实现、操作复杂度、实际应用等,帮助用户进一步理解。 现在,将这些点组织成一个结构清晰的回答,确保每个部分简明扼要,对比表格清晰,示例代码正确,并正确引用提供的资料。</think>#### C++中`map`与`multimap`的区别及使用场景详解 --- ### 一、核心区别对比 | **特性** | **`std::map`** | **`std::multimap`** | |---------------------|-----------------------------------|-----------------------------------| | **键唯一性** | 键必须唯一 | 允许重复键 | | **插入行为** | 插入重复键时失败(需手动判断) | 直接插入成功 | | **访问方式** | 支持`operator[]`按键快速访问值 | 不支持`operator[]`,需通过迭代器或范围查询 | | **典型操作复杂度** | 插入/删除/查找均为$O(\log n)$ | 同`map` | | **底层实现** | 红黑树(有序存储)[^3] | 红黑树(有序存储)[^3] | --- ### 二、具体差异解析 #### 1. **键的唯一性与插入行为** - **`map`**:每个键唯一,插入重复键时会覆盖原有值(或需通过`insert`返回值判断是否成功)。 ```cpp map<string, int> m; m["apple"] = 3; // 插入成功 m["apple"] = 5; // 覆盖原有值,m["apple"]=5 ``` - **`multimap`**:允许重复键,插入操作总是成功。 ```cpp multimap<string, int> mm; mm.insert({"apple", 3}); mm.insert({"apple", 5}); // 存储两个键为"apple"的键值对 ``` #### 2. **数据访问方式** - **`map`**:通过键直接访问值(`m[key]`),适合需要快速查找的场景。 ```cpp if (m.find("apple") != m.end()) cout << m["apple"]; // 输出5 ``` - **`multimap`**:需通过迭代器或`equal_range`获取相同键的所有值。 ```cpp auto range = mm.equal_range("apple"); for (auto it = range.first; it != range.second; ++it) cout << it->second << " "; // 输出3 5 ``` #### 3. **内存与性能** - **内存占用**:`multimap`因存储重复键可能占用更多内存。 - **查询效率**:两者查找复杂度均为$O(\log n)$,但`multimap`需处理多个相同键的遍历。 --- ### 三、典型应用场景 #### 1. **`map`的使用场景** - **键值唯一映射**:如用户ID到用户信息的存储。 - **快速查找与更新**:配置项管理、缓存系统。 ```cpp map<int, string> userDB; userDB[101] = "Alice"; // 用户ID唯一 ``` #### 2. **`multimap`的使用场景** - **一对多关系**:如事件调度(同一时间点多个事件)[^5]。 - **分组统计**:按频率排序单词(允许相同频率的单词)[^1][^2]。 ```cpp // 统计高频单词(引用[1]示例) map<string, int> wordCount; // ...统计单词频率 multimap<int, string, greater<int>> sortedByFreq; for (auto& e : wordCount) sortedByFreq.insert({e.second, e.first}); // 允许相同频率 ``` --- ### 四、选择依据 - **是否需要重复键**:是 → `multimap`;否 → `map`。 - **是否需要直接按键访问**:是 → `map`;否 → `multimap`。 - **是否需要有序遍历**:两者均支持有序遍历(基于红黑树)[^3]。 --- ### 五、代码示例对比 #### `map`的键唯一性 ```cpp map<int, string> taskMap; taskMap[2] = "Task 1"; taskMap[2] = "Task 2"; // 覆盖原有值,键2对应"Task 2" ``` #### `multimap`的重复键支持 ```cpp multimap<int, string> taskMultiMap; taskMultiMap.insert({2, "Task 1"}); taskMultiMap.insert({2, "Task 2"}); // 存储两个键为2的键值对 ``` --- ### 六、相关问题 1. **`map`的`operator[]`与`insert`方法有何区别?** - `operator[]`会覆盖已有键的值,`insert`返回插入结果(包含是否成功的标志)[^3]。 2. **如何高效遍历`multimap`中的所有重复键?** - 使用`equal_range`获取迭代器范围,避免线性搜索[^1][^5]。 3. **`multimap`与`unordered_multimap`的性能差异?** - `unordered_multimap`基于哈希表,查询平均$O(1)$,但无序且可能哈希冲突;`multimap`保持有序但查询为$O(\log n)$[^4]。 --- 通过上述对比,可以清晰理解`map`与`multimap`的核心差异及适用场景,从而在开发中合理选择容器类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值