mthoutai

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、简要概念

multiset是C++标准模板库(STL)中的一种关联式容器,用于存储可重复的唯一键值对元素。特性如下:

元素可重复:允许多个相同键值对的元素共存

底层实现‌:基于红黑树(一种平衡二叉树),支持高效查找、插入和删除操作

排序规则‌:元素按键值自动排序,默认使用<运算符,可通过自定义仿函数调整排序逻辑

两者的区别:

set不允许重复元素,即每个元素只能出现一次

multiset允许容器中有重复元素

两者共同点:

都是关联容器,基于红黑树实现,因此插入、删除和查找的时间复杂度都是O(log n)

元素都是自动排序的

使用时包含头文件 , #include<set>

二、基本定义

multiset<键类型,值类型,比较器> 变量名    默认比较器是升序

当比较器写为:greater<类型> 时, 为降序

例如:

// 定义一个存储 int 的 multiset,默认按 less 升序排列
multiset ms1;
// 定义一个降序排列的 multiset
multiset> ms2;
// 使用初始化列表初始化
multiset ms3 = {5, 2, 8, 2, 9, 2, 5};

一些简单的容器方法如:

clear()清空容器, empty()判空

begin() 返回首个元素的迭代器, end() 返回最后以一个元素的下一个位置的迭代器

三、常用方法以及使用

1. 基于迭代器的遍历
// 使用迭代器
for (multiset::iterator it = ms1.begin(); it != ms1.end(); ++it)
{
    cout << *it << " ";
}
2. 基于范围for循环(C++11)
//范围for循环 (C++11)
for (const auto& elem : ms)
{
    cout << elem << " ";
}
3. 插入元素insert

时间复杂度为 O(log n)

#include
#include
using namespace std;
int main
{
    multiset ms;
    ms.insert(10);
    ms.insert(20);
    ms.insert(10); // 允许插入重复值
    ms.insert(5);
    // 此时 ms 的内容: 5, 10, 10, 20
    //范围for循环 (C++11)
    for (const auto& elem : ms)
    {
        cout << elem << " ";
    }
    return 0;
}
4. 查找元素find(key)
#include
#include
using namespace std;
int main
{
    multiset ms;
    ms.insert(10);
    ms.insert(20);
    ms.insert(10); // 允许插入重复值
    ms.insert(5);
    auto it = ms.find(10);
    if (it != ms.end())
    {
        cout << "Found: " << *it << endl; // 输出: Found: 10
        // 注意:这里找到的是第一个 2
    }
    return 0;
}
5. 统计元素出现次数count(key)
#include
#include
using namespace std;
int main
{
    multiset ms;
    ms.insert(10);
    ms.insert(20);
    ms.insert(10); // 允许插入重复值
    ms.insert(5);
    cout << ms.count(10) << endl; // 输出: 2
    cout << ms.count(5) << endl; // 输出: 1
    return 0;
}
6. 删除元素erase

erase 有三种重载形式:

6.1 erase(iterator pos): 删除迭代器 pos 指向的元素
#include
#include
using namespace std;
int main
{
    multiset ms = {1, 2, 2, 3, 4};
    auto it = ms.find(2);
    if (it != ms.end())
    {
        ms.erase(it); // 只删除找到的第一个 2
    }
    // ms 现在为: 1, 2, 3, 4
    //范围for循环 (C++11)
    for (const auto& elem : ms)
    {
        cout << elem << " ";
    }
    return 0;
}
6.2 erase(const key_type& key): 删除所有值为 key 的元素,返回被删除的元素个数
#include
#include
using namespace std;
int main
{
    multiset ms = {1, 2, 2, 3, 4};
    size_t num_removed = ms.erase(2); // 删除所有的 2
    cout << num_removed << endl; // 输出: 2
    // ms 现在为: 1, 3, 4
    //范围for循环 (C++11)
    for (const auto& elem : ms)
    {
        cout << elem << " ";
    }
    return 0;
}
6.3 erase(iterator first, iterator last): 删除 [first, last) 区间内的所有元素。
#include
#include
using namespace std;
int main
{
    multiset ms = {1, 2, 3, 4, 5};
    // 删除 [2, 4) 区间,即 2 和 3
    auto it1 = ms.find(2);
    auto it2 = ms.find(4);
    ms.erase(it1, it2);
    // ms 现在为: 1, 4, 5
    //范围for循环 (C++11)
    for (const auto& elem : ms)
    {
        cout << elem << " ";
    }
    return 0;
}
7. 获取范围:equal_range

对于 multiset,处理重复元素时,equal_range是一个极其有用的函数。

它返回一个pair<iterator, iterator>,其中:

  • first是指向第一个不小于key的元素的迭代器(即 lower_bound)。

  • second是指向第一个大于key的元素的迭代器(即 upper_bound)。

这个区间 [first, second)包含了所有等于 key 的元素。

#include
#include
using namespace std;
int main
{
    multiset ms = {5, 2, 8, 2, 9, 2};
    // 获取所有等于 2 的元素的范围
    auto range = ms.equal_range(2);
    // 遍历这个范围,打印所有的 2
    for (auto it = range.first; it != range.second; ++it)
    {
        cout << *it << " "; // 输出: 2 2 2
    }
    cout << endl;
    return 0;
}
8. 获取边界:lower_bound和 upper_bound
  • lower_bound(key): 返回指向第一个不小于key 的元素的迭代器。

  • upper_bound(key): 返回指向第一个大于key 的元素的迭代器。

#include
#include
using namespace std;
int main
{
    multiset ms = {1, 2, 2, 3, 4};
    // 找到 [2, 3) 区间
    auto low = ms.lower_bound(2); // 指向第一个 2
    auto up = ms.upper_bound(2);  // 指向 3
    for (auto it = low; it != up; ++it)
    {
        cout << *it << " "; // 输出: 2 2
    }
    return 0;
}

posted on 2025-10-27 15:33  mthoutai  阅读(1)  评论(0)    收藏  举报