C++ STL 中的 set 和 multiset 容器详解2

C++ STL 中的 setmultiset 容器详解 2

概述

在 C++ 标准模板库(STL)中,setmultiset 是两种非常重要的关联容器。它们都基于红黑树实现,能够自动对元素进行排序。本文将详细解析这两种容器的特性、用法和区别。

头文件引入

#include <set>
#include <algorithm>
#include <functional>
#include <iostream>
  • <set>:包含 setmultiset 的定义
  • <algorithm>:提供各种算法操作
  • <functional>:包含函数对象和操作符
  • <iostream>:标准输入输出流

set 容器

基本特性

set 是一个有序唯一键集合,具有以下特点:

  1. 自动排序:元素插入后会自动按升序排列
  2. 唯一性:不允许有重复元素
  3. 不可修改元素值:元素值一旦插入就不能修改,只能删除后重新插入

初始化与插入

set<int> setInt;
for (int i = 5; i > 0; i--) {
    setInt.insert(i);  // 插入元素
}
  • 这里我们创建了一个 set<int> 容器 setInt
  • 使用 insert() 方法插入元素
  • 虽然我们按 5,4,3,2,1 的顺序插入,但 set 会自动排序为 1,2,3,4,5

拷贝构造与赋值

set<int> setInt1(setInt);  // 拷贝构造函数
set<int> setInt2(setInt1);  // 另一个拷贝构造

setInt2.insert(666);  // 插入新元素
setInt2.swap(setInt1);  // 交换两个set的内容
  • set 支持拷贝构造函数,可以基于现有 set 创建新 set
  • swap() 方法可以高效交换两个 set 的内容

遍历与输出

set<int>::iterator it = setInt1.begin();
for (; it != setInt1.end(); ++it) {
    cout << *it << " ";
}
  • 使用迭代器遍历 set
  • begin() 返回指向第一个元素的迭代器
  • end() 返回指向最后一个元素之后的迭代器
  • 迭代器支持 ++ 操作符移动到下一个元素
  • 使用 * 解引用迭代器获取元素值

multiset 容器

基本特性

multisetset 类似,但有重要区别:

  1. 允许重复元素
  2. 同样保持元素有序
  3. 基于红黑树实现

基本操作

multiset<int> mulInt;
mulInt.insert(99);  // 可以插入重复值
  • multiset 的接口与 set 基本一致
  • 主要区别在于允许插入重复值

关键知识点总结

1. 自动排序

setmultiset 都会自动对元素进行排序,默认是升序排列。可以通过自定义比较函数改变排序方式。

2. 元素唯一性

  • set:保证元素的唯一性,插入重复元素会被忽略
  • multiset:允许重复元素存在

3. 迭代器

  • 使用双向迭代器,可以向前和向后遍历
  • 迭代器遍历时按排序顺序访问元素
  • 迭代器失效:只有被删除元素的迭代器会失效,其他迭代器不受影响

4. 常用操作

操作描述时间复杂度
insert()插入元素O(log n)
erase()删除元素O(log n)
find()查找元素O(log n)
size()返回元素数量O(1)
empty()检查是否为空O(1)
clear()清空容器O(n)

5. 性能特点

由于基于红黑树实现,setmultiset 提供较好的综合性能:

  • 查找、插入、删除都是 O(log n) 复杂度
  • 元素有序存储,适合需要有序访问的场景
  • 相比 unordered_set,内存占用更小但访问速度稍慢

实际应用场景

  1. 需要有序且唯一元素的集合:使用 set
  2. 需要有序但允许重复的集合:使用 multiset
  3. 频繁查找的场景:两者都适合
  4. 需要按顺序处理的元素集合:如按分数排序的学生成绩

注意事项

  1. set 中的元素是const的,不能直接修改
  2. 插入自定义类型时需要提供比较函数
  3. 迭代器遍历时,元素是按排序顺序访问的
  4. 删除元素时要小心迭代器失效问题

完整代码回顾

#include <set>
#include <algorithm>
#include <functional>
#include <iostream>

using namespace std;

int main(void) {
    // 创建并初始化set
    set<int> setInt;
    for (int i = 5; i > 0; i--) {
        setInt.insert(i);  // 插入元素,自动排序
    }
    
    // set的拷贝构造
    set<int> setInt1(setInt);
    set<int> setInt2(setInt1);
    
    // 插入新元素和交换
    setInt2.insert(666);
    setInt2.swap(setInt1);
    
    // 遍历输出
    cout << "setInt1:" << endl;
    for (auto it = setInt1.begin(); it != setInt1.end(); ++it) {
        cout << *it << " ";
    }
    
    cout << "\nsetInt2:" << endl;
    for (auto it = setInt2.begin(); it != setInt2.end(); ++it) {
        cout << *it << " ";
    }
    
    // multiset演示
    multiset<int> mulInt;
    mulInt.insert(99);  // 允许重复插入
    
    system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值