在 C++ 中,setmultiset 都是基于平衡二叉搜索树(通常是红黑树)实现的容器。它们的主要作用是存储元素并自动排序,且提供了高效的查找、插入和删除操作。它们属于 STL(标准模板库)的关联容器,用于存储有序的元素。

1. set 容器

定义与特点:
  • set 是一个集合,存储的是唯一的元素,每个元素在集合中只能出现一次。
  • 元素是按照升序(默认)或自定义排序规则排序的。
  • set 不允许重复元素,如果尝试插入重复的元素,插入操作会失败(即不插入该元素)。
常用操作:
  • 插入元素insert(),可以用来插入新元素。若插入的元素已存在,插入会失败,且不会修改原来的集合。
  • 查找元素find(),返回一个指向找到的元素的迭代器。如果没有找到,返回 end()
  • 删除元素erase(),根据元素的值删除。如果提供的是迭代器,则删除该迭代器指向的元素。
  • 大小size(),返回集合中元素的个数。
  • 是否为空empty(),检查集合是否为空。
  • 最小值与最大值begin() 和 end(),返回指向第一个元素和尾后元素的迭代器。
示例:
#include <iostream>
#include <set>

int main() {
    std::set<int> mySet;
    
    // 插入元素
    mySet.insert(10);
    mySet.insert(20);
    mySet.insert(10);  // 重复元素,不会插入

    // 打印集合中的元素
    for (int x : mySet) {
        std::cout << x << " ";
    }

    std::cout << "\n";
    return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

输出:

10 20
  • 1.

2. multiset 容器

定义与特点:
  • multiset 是一个多重集合,允许集合中出现重复的元素。
  • 元素是自动排序的,且可以按照升序或自定义排序规则排序。
  • multiset 可以存储多个相同的元素,并且会根据插入顺序排序。
常用操作:
  • 插入元素insert(),允许插入重复的元素。
  • 查找元素find(),返回一个指向找到的元素的迭代器。与 set 不同,multiset 可能有多个相同的元素。
  • 删除元素erase(),可以根据元素值删除指定的元素。通过迭代器删除时删除该迭代器指向的元素。
  • 大小size(),返回容器中元素的个数。
  • 删除指定元素的所有实例erase(key),删除所有与 key 相同的元素。
示例:
#include <iostream>
#include <set>

int main() {
    std::multiset<int> myMultiSet;
    
    // 插入元素
    myMultiSet.insert(10);
    myMultiSet.insert(20);
    myMultiSet.insert(10);  // 插入重复元素

    // 打印集合中的元素
    for (int x : myMultiSet) {
        std::cout << x << " ";
    }

    std::cout << "\n";
    return 0;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.

输出:

10 10 20
  • 1.

3. set 和 multiset 的区别

特性

set

multiset

元素的唯一性

每个元素只能出现一次

允许重复元素

查找操作

查找一个元素返回一个指向该元素的迭代器

查找一个元素返回一个指向该元素的迭代器(可能是多个元素)

插入操作

如果元素已存在,插入失败

插入操作始终成功

适用场景

需要唯一元素的场景

需要存储多个相同元素的场景

4. 其他相关操作和技巧

  • 自定义排序:你可以为 setmultiset 提供一个自定义的比较器来改变默认的排序方式。
struct CustomCompare {
    bool operator()(int a, int b) {
        return a > b;  // 降序排列
    }
};

std::set<int, CustomCompare> customSet;
customSet.insert(10);
customSet.insert(20);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 计数元素的个数:可以使用 count() 方法来查找某个元素出现的次数(适用于 multiset)。
std::multiset<int> myMultiSet;
myMultiSet.insert(10);
myMultiSet.insert(10);
std::cout << "Count of 10: " << myMultiSet.count(10) << std::endl;  // 输出 2
  • 1.
  • 2.
  • 3.
  • 4.

5. 性能

  • 插入、删除、查找操作的时间复杂度O(log n)。由于底层实现是平衡二叉搜索树(如红黑树),因此这些操作都是对数时间复杂度。

总结

  • set:用于存储唯一的元素,并自动按升序排列。
  • multiset:用于存储多个相同的元素,也会自动排序,但允许重复元素。

这些容器在需要进行高效查找、插入和删除操作时非常有用,尤其适合处理有序数据和去重需求的场景。