multiset用法用法介绍(set/multiset)

一、multiset简介

multiset是C++ STL(Standard Template Library)的一种关联式容器(Associative Container),基于红黑树实现。它可以存储任意类型的元素,并且自动按照元素的大小进行排序。multiset允许元素重复,在排序的时候不会把相同元素视作同一个。


// 代码示例:
#include <set>
#include <iostream>

int main() {
    std::multiset<int> ms;
    ms.insert(5);
    ms.insert(2);
    ms.insert(7);
    ms.insert(2);
    ms.insert(4);

    for (auto it = ms.begin(); it != ms.end(); ++it) {
        std::cout << *it << " ";
    }

    return 0;
}

// 输出结果:
// 2 2 4 5 7

从上面的代码示例中可以看出,multiset允许重复元素,并且在遍历时按照元素大小自动排序。

二、multiset的基本用法

1. 添加元素

multiset提供了多种添加元素的方法,具体如下:

  • insert():向multiset中添加元素。
  • emplace():在multiset中直接生成元素。
  • emplace_hint():在指定位置处直接生成元素,并返回生成元素的迭代器。

// 代码示例:
#include <set>
#include <iostream>

int main() {
    std::multiset<int> ms;
    ms.insert(5);
    ms.insert(2);
    ms.emplace(3);
    ms.emplace_hint(ms.end(), 4);

    for (auto it = ms.begin(); it != ms.end(); ++it) {
        std::cout << *it << " ";
    }

    return 0;
}

// 输出结果:
// 2 3 4 5

从上面的代码示例中可以看出,multiset添加元素的方法使用起来非常简单。

2. 删除元素

multiset提供了多种删除元素的方法,具体如下:

  • erase():从multiset中删除指定元素。
  • clear():清空multiset中所有元素。

// 代码示例:
#include <set>
#include <iostream>

int main() {
    std::multiset<int> ms;
    ms.insert(5);
    ms.insert(2);
    ms.insert(3);
    ms.insert(4);

    ms.erase(2);

    for (auto it = ms.begin(); it != ms.end(); ++it) {
        std::cout << *it << " ";
    }

    ms.clear();

    std::cout << "n" << ms.size() << std::endl;

    return 0;
}

// 输出结果:
// 3 4 5 
// 0

从上面的代码示例中可以看出,multiset删除元素的方法使用起来非常简单。

3. 查找元素

multiset提供了多种查找元素的方法,具体如下:

  • count():查找multiset中指定元素的个数。
  • find():查找multiset中指定元素的位置。
  • equal_range():返回multiset中指定元素的范围。
  • lower_bound():返回multiset中第一个大于或等于指定元素的位置。
  • upper_bound():返回multiset中第一个大于指定元素的位置。

// 代码示例:
#include <set>
#include <iostream>

int main() {
    std::multiset<int> ms;
    ms.insert(5);
    ms.insert(2);
    ms.insert(3);
    ms.insert(4);

    std::cout << ms.count(2) << std::endl;

    auto it = ms.find(3);
    if (it != ms.end()) {
        std::cout << *it << std::endl;
    }

    auto range = ms.equal_range(4);
    for (auto i = range.first; i != range.second; ++i) {
        std::cout << *i << " ";
    }

    std::cout << std::endl;

    auto lb = ms.lower_bound(3);
    if (lb != ms.end()) {
        std::cout << *lb << std::endl;
    }

    auto ub = ms.upper_bound(3);
    if (ub != ms.end()) {
        std::cout << *ub << std::endl;
    }

    return 0;
}

// 输出结果:
// 1
// 3
// 4 
// 3
// 4

从上面的代码示例中可以看出,multiset查找元素的方法使用起来非常方便。

三、multiset的高级用法

1. 元素比较函数

multiset可以通过指定元素比较函数自定义元素排序规则。


// 代码示例:
#include <set>
#include <iostream>

struct Student {
    int id;
    std::string name;
    int score;
};

bool cmp(const Student& s1, const Student& s2) {
    return s1.score > s2.score; // 按照分数从高到低排序
}

int main() {
    std::multiset<Student, bool (*)(const Student&, const Student&)> ms(cmp);

    ms.insert({1, "Tom", 70});
    ms.insert({2, "Jerry", 90});
    ms.insert({3, "Mike", 80});

    for (auto it = ms.begin(); it != ms.end(); ++it) {
        std::cout <name << " " <score << std::endl;
    }

    return 0;
}

// 输出结果:
// Jerry 90
// Mike 80
// Tom 70

从上面的代码示例中可以看出,multiset可以通过自定义比较函数来排序元素。

2. 自定义存储类型

multiset可以存储任意类型的元素,我们也可以自定义存储类型。需要注意的是,自定义存储类型需要提供比较运算符(operator<)。


// 代码示例:
#include <set>
#include <iostream>

class Point {
public:
    int x;
    int y;

    Point() : x(0), y(0) {}
    Point(int x_, int y_) : x(x_), y(y_) {}

    bool operator<(const Point& other) const {
        if (x != other.x) {
            return x < other.x;
        }
        return y < other.y;
    }
};

int main() {
    std::multiset<Point> ms;

    ms.insert({1, 2});
    ms.insert({4, 3});
    ms.insert({3, 5});

    for (auto it = ms.begin(); it != ms.end(); ++it) {
        std::cout << "(" <x << "," <y << ")" << std::endl;
    }

    return 0;
}

// 输出结果:
// (1,2)
// (3,5)
// (4,3)

从上面的代码示例中可以看出,multiset可以存储自定义类型的元素,并且自动按照元素大小排序。

3. 迭代器失效问题

multiset的插入、删除操作会导致迭代器失效,需要重新获取。尤其是在使用erase()方法删除元素时,需要注意。


// 代码示例:
#include <set>
#include <iostream>

int main() {
    std::multiset<int> ms;
    ms.insert(5);
    ms.insert(2);
    ms.insert(3);

    auto it = ms.find(2);
    if (it != ms.end()) {
        ms.erase(it);
    }

    for (auto it = ms.begin(); it != ms.end(); ++it) {
        std::cout << *it << " ";
    }

    return 0;
}

// 输出结果:
// 3 5

从上面的代码示例中可以看出,使用erase()方法删除元素时需要注意迭代器失效问题。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平