multimap和multiset 认知和使用

本文详细介绍了C++中multimap和multiset容器的特点及应用,包括如何通过find、count等函数查找元素,并对比了有序与无序容器的不同实现。

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

之前只是在C++ Primer里面看过关联容器,可能因为没有实际用过,只是看看,所以导致用的时候并不熟悉;

在这之前,map和set的特性应该要了解,map是关联数组,也就是由键值对组成的,而set只是关键字的集合,但是两者都只允许关键字是唯一的,也就是对于一个给定的关键字,它只能允许一个元素的关键字等于它;
但是,容器multimap和multiset并没有这个限制,它们都允许多个元素具有相同的关键字。

如何访问multimap呢,也就是如何查找元素呢?

这个时候需要先了解multimap的函数:

find(k) 返回第一个关键字为k的迭代器
count(k) 返回关键字等于k的个数
lower_bound(k) 返回第一个关键字不小于k的元素
upper_bound(k) 返回第一个关键字大于k的元素
equal_bound(k) 上面返回的是迭代器,但是这里返回的迭代器pair,表示关键字等于k的元素的范围,若k不存在,pair的两个成员均等于end()

注意:多个相同的关键字存储在容器中时,则会相邻存储;

根据以上的函数,可以使用三种方法进行查找元素

第一种方法:find + count

multimap<string, int> maps;
string word("word");
//注意是第一个出现的
auto itr = maps.find(word);
auto cnt = maps.count(word);
//循环便利
while (cnt) {
    cout << itr->second << endl;
    ++itr;
    cnt--;
}
    

第二种方法:lower_bound + upper_bound

multimap<string, int> maps;
string word("word");
//其实就是一个区间,因为存储位置连续
for (auto beg = maps.lower_bound(word), end = maps.upper_bound(word); beg != end; ++beg) {
    cout << beg->second << endl;
}

第三种方法:equal_range

multimap<string, int> maps;
string word("word");
// 和上面不一样,直接返回一个区间
for (auto pos = maps.equal_range(word); pos.first != maps.end(); ++pos.first) {
    cout << pos.first->second << endl;
}

对了还有unordered,这是没有进行排序的,同样的这些无序容器同样有重复关键字的版本-unordered_multimap,unordered_multiset,这些是用哈希函数实现,没有unordered的则是用红黑树实现的。

转载于:https://www.cnblogs.com/George1994/p/6260763.html

<think>好的,我现在需要回答用户关于multimapmultiset的底层实现原理及区别的问题。首先,我得仔细看看用户提供的引用内容,看看有没有相关的信息可以引用。 根据引用[2]引用[3],提到multimapmultiset属于树型结构的关联容器,底层使用红黑树实现。红黑树是一种平衡二叉搜索树,能够自动调整结构以保持平衡,这样插入、删除查找操作的时间复杂度都是O(log n)。multimapmultiset允许键重复,而mapset不允许,这也是它们的主要区别之一。 接下来,关于multimap的具体实现,引用[4]提到map中的键值对通过value_type绑定为pair类型,而multimap作为其允许重复键的版本,应该也是类似的实现。multisetset类似,但允许重复元素存在。引用[5]还提到multimap的操作,如insert、erase等,这些操作在红黑树结构下如何实现可能需要进一步解释。 用户还问到底层实现的区别。需要强调两者虽然都是红黑树,但multimap存储的是键值对,而multiset只存储单个值。另外,两者的应用场景不同,比如multimap适合需要按键排序且允许重复键的情况,如事件调度;multiset适合需要有序且允许重复元素的集合,如成绩统计。 在用法上,引用[3]中的代码示例展示了如何使用multimap来按出现次数排序字符串,这可以作为一个例子说明multimap的插入遍历方法。而multiset的用法可能更直接,比如统计元素出现的次数,或者维护一个有序的重复元素集合。 需要注意用户可能对红黑树的具体实现细节不太熟悉,所以需要以简明的方式解释,避免过于技术化。同时,结合引用中的内容,确保信息准确,并适当标注引用来源。 最后,生成相关问题时要围绕底层原理、操作方法使用场景展开,帮助用户进一步理解这两个容器的特点应用。</think>### multimapmultiset的底层实现原理及区别 #### 一、底层实现原理 1. **数据结构基础** multimapmultiset均基于**红黑树**(平衡二叉搜索树)实现[^2]。红黑树通过自动平衡机制(颜色标记、旋转操作)保证插入、删除、查找操作的时间复杂度为$O(\log n)$,同时维护元素的有序性。 2. **multimap的实现特点** - 存储键值对`pair<const Key, Value>`,允许**重复的键**存在[^4]。 - 内部按键(Key)进行排序,排序规则可通过自定义比较函数指定。 - 示例:`multimap<int, string>`会将键相同的多个键值对按插入顺序排列[^3]。 3. **multiset的实现特点** - 存储单一元素(Value),允许**重复元素**存在。 - 元素本身即为排序依据,默认按升序排列。 - 示例:`multiset<int> {3,1,2,2}`会存储为有序序列`{1,2,2,3}`[^2]。 #### 二、核心区别 | 特性 | multimap | multiset | |---------------------|-----------------------------------|-------------------------| | **存储内容** | 键值对(Key-Value) | 单一元素(Value) | | **排序依据** | 键(Key) | 元素本身(Value) | | **重复性支持** | 允许重复键 | 允许重复元素 | | **典型操作** | 插入键值对、范围查询(equal_range)| 插入元素、统计出现次数 | #### 三、具体用法示例 1. **multimap的插入遍历** ```cpp multimap<string, int> mmp; mmp.insert({"apple", 3}); mmp.insert({"apple", 5}); // 允许重复键 for (auto it = mmp.begin(); it != mmp.end(); ++it) { cout << it->first << ":" << it->second << endl; // 输出有序键值对 } ``` 2. **multiset的统计删除** ```cpp multiset<int> ms = {2, 2, 3, 1}; ms.erase(2); // 删除所有值为2的元素 int count = ms.count(3); // 返回元素3的出现次数(1次) ``` #### 四、应用场景 - **multimap**:适用于需要按键排序且允许重复键的场景,如**事件调度系统**(同一时间点多个事件)[^3]。 - **multiset**:适合需要有序且允许重复元素的场景,如**成绩排名统计**(允许相同分数存在)[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值