关于Multimap的遍历和删除

本文介绍了C++标准模板库(STL)中的关联容器multimap的使用方法,包括如何遍历multimap并输出键值对,如何使用count函数计算一个键对应的值的数量,以及如何通过equal_range函数和erase函数来删除指定的键值对。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++的STL的关联容器multimap允许一个key值对应多个值,当对整个multimap进行遍历时可以使用迭代器,迭代器会指向多个键值对,而不是一个键值后的多个值,当希望输出key:value1 value2...形式时,需要使用count函数计算一个key值包含多少个值,然后使用循环对迭代器自增输出这些值。

当需要删除多个值中的某一个时,使用equal_range函数保存某一key值对应所有值的起始位置,这两个位置保存在一个pair对中,用first值遍历这些值,找到符合条件的删除,否则自增,由于删除操作会使迭代器失效,故将erase函数的返回值赋值给first迭代器,令其指向删除元素的下一个元素,保证first迭代器不会失效。

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main ()
{
	multimap<string,int> authors;
	for (int i=0;i<10;i++)//初始化一个multimap
	{
		for (int j=0;j<=i;j++)
		{
			string s;
			s+='a'+j;
			authors.insert(make_pair(s,i));
			authors.insert(make_pair(s,i-1));
		}	
	}
	multimap<string,int>::iterator map_it=authors.begin();
	typedef multimap<string,int>::iterator authors_it;
	cout<<"原multimap容器:"<<endl;
	while (map_it!=authors.end())//遍历multimap容器,由于map_it一次指向包含一个键值对,例如,当前map_it指向(a,0),自增之后指向(a,1)
				     //故仅在第一次输出first值,使用count函数计算该键对应的值个数,然后循环输出各second值,同时增加map_it
	{
		
		cout<<map_it->first<<":";
	
		typedef multimap<string,int>::size_type sz_type;//multimap数量类型
		sz_type cnt=authors.count(map_it->first);//返回一个键对应的值个数
		for (sz_type i=0;i!=cnt;++map_it,++i)//循环输出各值,同时自增map_it
		{
			cout<<map_it->second<<" ";
		}
		cout<<endl;
	}
	
	map_it=authors.find("c");//删除(c,5)
	pair<authors_it,authors_it> pos=authors.equal_range(map_it->first);//利用一对multimap<string,int>指向第一个出现(c,5)的位置和最后一个出现(c,5)的位置
	while (pos.first!=pos.second)
	{
		if (pos.first->second==5)//当pos指向5时
		{	
			pos.first=authors.erase(pos.first);//删除后会改变pos迭代器,故赋值给自身,指向删除后的下一个键值对
		}
		else
			++pos.first;//不进行删除操作则自增
		
	}
	cout<<"删除(c,5)之后的multimap容器:"<<endl;//输出删除(c,5)之后的multimap
	map_it=authors.begin();
	while (map_it!=authors.end())//遍历multimap容器,由于map_it一次指向包含一个键值对,例如,当前map_it指向(a,0),自增之后指向(a,1)
				     //故仅在第一次输出first值,使用count函数计算该键对应的值个数,然后循环输出各second值,同时增加map_it
	{

		cout<<map_it->first<<":";

		typedef multimap<string,int>::size_type sz_type;//multimap数量类型
		sz_type cnt=authors.count(map_it->first);//返回一个键对应的值个数
		for (sz_type i=0;i!=cnt;++map_it,++i)//循环输出各值,同时自增map_it
		{
			cout<<map_it->second<<" ";
		}
		cout<<endl;
	}
	system("pause");
	return 0;
}


<think>嗯,用户现在问的是C++中inserterase函数的功能用法。之前他们问过关于vector的insert方法的具体例子,现在可能想扩展了解这两个函数更全面的内容。首先,我需要回忆这两个函数在STL容器中的常见用法,比如vector、list、string、map等。 用户可能是在学习STL容器,或者在做项目时需要操作容器元素。他们可能已经知道一些基本操作,但想深入了解inserterase在不同容器中的差异使用场景。需要确保覆盖主要容器类型,并提供示例,这样用户更容易理解。 首先,insert函数的功能是向容器中添加元素,但不同的容器有不同的插入方式。比如vector的insert在指定位置插入,而map的insert则是插入键值对。同样,erase用于删除元素,但删除单个元素范围的方式不同,且关联容器如map的erase可以用键来删除。 需要注意用户可能对迭代器的有效性有疑问,比如在vector中插入或删除后迭代器是否会失效,这时候应该提到这一点,作为注意事项。此外,对于关联容器无序容器的不同,比如multimap允许重复键,而map不允许,这些差异也要说明。 还要考虑用户可能的常见错误,比如越界访问或者在循环中删除元素导致的问题,应该给出示例解决方法,比如使用erase返回的迭代器来安全删除。 可能需要比较不同容器使用inserterase的效率,比如list的插入删除比vector高效,因为不需要移动元素。这样用户可以根据场景选择合适的容器。 最后,总结两者的功能,强调参数返回值的不同,以及在不同容器中的行为差异。确保语言简洁,示例清晰,避免使用过于专业的术语,但又要准确。</think>在 C++ 中,`insert` `erase` 是 STL 容器(如 `vector`、`list`、`string`、`map` 等)中常用的成员函数,用于动态修改容器内容。以下是它们的核心功能使用方法: --- ### **`insert` 函数** #### **功能** 向容器的**指定位置**插入一个或多个元素。 #### **常见用法** 不同容器的 `insert` 语法略有差异,以下是典型场景: 1. **顺序容器(`vector`, `list`, `deque`, `string` 等)** - 插入单个元素: ```cpp iterator insert(iterator pos, const T& value); ``` ```cpp std::vector<int> vec{1, 2, 3}; auto it = vec.insert(vec.begin() + 1, 99); // 在索引1处插入99 → {1, 99, 2, 3} ``` - 插入多个相同元素: ```cpp void insert(iterator pos, size_t n, const T& value); ``` ```cpp vec.insert(vec.end(), 3, 100); // 末尾插入3个100 → {1, 99, 2, 3, 100, 100, 100} ``` - 插入一个区间的元素(迭代器范围): ```cpp template <class InputIterator> void insert(iterator pos, InputIterator first, InputIterator last); ``` ```cpp std::vector<int> src{4, 5, 6}; vec.insert(vec.end(), src.begin(), src.end()); // 末尾追加src的内容 ``` 2. **关联容器(`map`, `set`, `multimap` 等)** - 插入键值对(`map`/`multimap`): ```cpp std::map<int, string> m; m.insert(std::make_pair(1, "Apple")); // 插入键值对 ``` - 插入范围(迭代器区间): ```cpp m.insert(other_map.begin(), other_map.end()); // 合并另一个map的内容 ``` 3. **C++11 后的高效插入(`emplace`)** ```cpp vec.emplace(vec.begin(), "直接构造元素"); // 避免拷贝,直接构造 m.emplace(2, "Banana"); // 直接在容器内构造键值对 ``` --- ### **`erase` 函数** #### **功能** 从容器中**删除指定位置或范围的元素**。 #### **常见用法** 1. **顺序容器** - 删除单个元素: ```cpp iterator erase(iterator pos); ``` ```cpp std::vector<int> vec{1, 2, 3, 4}; auto it = vec.erase(vec.begin() + 1); // 删除索引1处的元素 → {1, 3, 4} // it 指向被删除元素的下一个位置(即原来的3) ``` - 删除元素范围: ```cpp iterator erase(iterator first, iterator last); ``` ```cpp vec.erase(vec.begin(), vec.begin() + 2); // 删除前2个元素 → {4} ``` 2. **关联容器** - 通过迭代器删除: ```cpp std::map<int, string> m{{1, "A"}, {2, "B"}}; m.erase(m.find(2)); // 删除键为2的元素 ``` - 通过键直接删除: ```cpp size_t count = m.erase(1); // 删除键为1的元素,返回成功删除的数量(0或1) ``` 3. **字符串(`string`)** ```cpp std::string str = "Hello World"; str.erase(5, 6); // 从索引5开始删除6个字符 → "Hello" ``` --- ### **关键注意事项** 1. **迭代器失效问题** - 在 `vector`/`string` 中,插入或删除元素可能导致**所有迭代器失效**(尤其是插入导致扩容时)。 - 在 `list`/`map` 中,只有被删除元素的迭代器失效,其他迭代器仍有效。 2. **性能差异** - `vector` 的 `insert`/`erase` 时间复杂度为 **O(n)**(需要移动后续元素)。 - `list`/`map` 的 `insert`/`erase` 时间复杂度为 **O(1)**(链表或树结构操作)。 3. **关联容器的唯一性** - `map`/`set` 的 `insert` 不会覆盖重复键,需用 `operator[]` 或 `emplace` 修改值。 --- ### **示例代码** #### 1. 在 `vector` 中删除符合条件的元素 ```cpp std::vector<int> vec{1, 2, 3, 4, 5}; // 删除所有偶数(需用 erase 返回的新迭代器) for (auto it = vec.begin(); it != vec.end(); ) { if (*it % 2 == 0) { it = vec.erase(it); // 删除后返回下一个有效迭代器 } else { ++it; } } // vec 变为 {1, 3, 5} ``` #### 2. 在 `map` 中插入删除 ```cpp std::map<int, std::string> m; m.insert({1, "Apple"}); m[2] = "Banana"; // operator[] 插入或覆盖 m.erase(1); // 删除键为1的元素 ``` --- ### **总结** | 函数 | 适用容器 | 核心功能 | 时间复杂度 | |----------|-------------------|------------------------------|------------------| | `insert` | 所有容器 | 动态添加元素 | 依赖容器结构 | | `erase` | 所有容器 | 动态删除元素 | 依赖容器结构 | 掌握 `insert` `erase` 是操作 C++ 容器的核心技能,需结合具体容器类型场景灵活使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值