C++中的set容器详解

C++中的set容器详解

1. set概述

set是C++ STL中的关联容器,它存储唯一元素 并按特定顺序自动排序。set基于红黑树实现,提供高效的查找、插入和删除操作。

2. 基本特性

  • 唯一性:所有元素都是唯一的
  • 自动排序:元素总是按指定排序规则排列
  • 不可修改元素:元素值不能被直接修改
  • 高效操作 :查找、插入、删除的时间复杂度为O(log⁡2n)O(\log_2 n)O(log2n)

3. 头文件与声明

cpp 复制代码
#include <set>
using namespace std;

set<int> s1;                     // 空set,默认升序
set<int, greater<int>> s2;       // 空set,降序排列
set<string> s3 = {"a", "b"};     // 初始化列表

4. 构造函数与初始化

4.1 默认构造

cpp 复制代码
set<int> s;  // 创建空set

4.2 范围构造

cpp 复制代码
int arr[] = {1, 2, 3};
set<int> s(arr, arr+3);  // 用数组范围构造

4.3 拷贝构造

cpp 复制代码
set<int> s2(s1);  // 拷贝构造

5. 容量操作

5.1 size()

cpp 复制代码
cout << s.size();  // 返回元素数量

5.2 empty()

cpp 复制代码
if(s.empty()) {
    cout << "Set is empty";
}

5.3 max_size()

cpp 复制代码
cout << s.max_size();  // 返回set可容纳的最大元素数

6. 修改操作

6.1 insert()

cpp 复制代码
s.insert(10);                  // 插入单个元素
s.insert({1, 2, 3});           // 插入多个元素
s.insert(s.begin(), 5);        // 带提示插入(不一定提高效率)

6.2 emplace()

cpp 复制代码
s.emplace(10);  // 原地构造元素,比insert更高效

6.3 erase()

cpp 复制代码
s.erase(10);                   // 删除值为10的元素
s.erase(s.begin());            // 删除迭代器指向的元素
s.erase(s.begin(), s.end());   // 删除范围元素

6.4 clear()

cpp 复制代码
s.clear();  // 清空所有元素

7. 查找操作

7.1 find()

cpp 复制代码
auto it = s.find(10);  // 查找元素,返回迭代器
if(it != s.end()) {
    cout << "Found: " << *it;
}

7.2 count()

cpp 复制代码
if(s.count(10)) {  // 返回匹配元素的数量(0或1)
    cout << "Element exists";
}

7.3 lower_bound() & upper_bound()

cpp 复制代码
auto lb = s.lower_bound(5);  // 返回第一个不小于5的元素
auto ub = s.upper_bound(10); // 返回第一个大于10的元素

7.4 equal_range()

cpp 复制代码
auto range = s.equal_range(5);  // 返回等于5的元素范围
// range.first是lower_bound, range.second是upper_bound

8. 迭代器

8.1 begin() & end()

cpp 复制代码
for(auto it = s.begin(); it != s.end(); ++it) {
    cout << *it << " ";
}

8.2 rbegin() & rend()

cpp 复制代码
for(auto rit = s.rbegin(); rit != s.rend(); ++rit) {
    cout << *rit << " ";  // 反向遍历
}

9. 完整示例

cpp 复制代码
#include <iostream>
#include <set>
using namespace std;

int main() {
    // 创建并初始化set
    set<int> s = {5, 2, 8, 1, 3};
    
    // 插入元素
    s.insert(4);
    s.emplace(6);
    
    // 查找元素
    if(s.find(3) != s.end()) {
        cout << "3 found in set\n";
    }
    
    // 删除元素
    s.erase(2);
    
    // 遍历set
    cout << "Set elements: ";
    for(int num : s) {
        cout << num << " ";  // 自动排序输出: 1 3 4 5 6 8
    }
    cout << endl;
    
    // 范围查询
    auto low = s.lower_bound(3);
    auto up = s.upper_bound(5);
    cout << "Elements between 3 and 5: ";
    for(auto it = low; it != up; ++it) {
        cout << *it << " ";  // 输出: 3 4 5
    }
    cout << endl;
    
    // 容量信息
    cout << "Size: " << s.size() << endl;
    cout << "Is empty: " << (s.empty() ? "Yes" : "No") << endl;
    
    return 0;
}

10. 自定义排序规则

cpp 复制代码
struct CaseInsensitiveCompare {
    bool operator()(const string& a, const string& b) const {
        return strcasecmp(a.c_str(), b.c_str()) < 0;
    }
};

set<string, CaseInsensitiveCompare> caseInsensitiveSet;

11. 性能提示

  1. 查找操作优先使用find()而非count()
  2. 插入大量数据时,考虑预先排序后再构造set
  3. 需要修改元素值时,应先删除再插入新值
  4. 使用emplace()替代insert()可避免不必要的拷贝
相关推荐
于小猿Sup18 分钟前
VMware在Ubuntu22.04驱动Livox Mid360s
linux·c++·嵌入式硬件·自动驾驶
cen__y31 分钟前
Linux12(Git01)
linux·运维·服务器·c语言·开发语言·git
AI人工智能+电脑小能手35 分钟前
【大白话说Java面试题 第65题】【JVM篇】第25题:谈谈对 OOM 的认识
java·开发语言·jvm
社交怪人1 小时前
【算平均分】信息学奥赛一本通C语言解法(题号2071)
c语言·开发语言
郭涤生2 小时前
不同主机之间网络通信-以太网连接复习
开发语言·rk3588
山居秋暝LS2 小时前
【无标题】RTX00安装paddle OCR,win11不能装最新的,也不能用GPU
开发语言·r语言
卢锡荣2 小时前
单芯通吃,盲插标杆 —— 乐得瑞 LDR6020,Type‑C 全场景互联 “智慧芯”
c语言·开发语言·计算机外设
Xin_ye100862 小时前
C# 零基础到精通教程 - 第七章:面向对象编程(入门)——类与对象
开发语言·c#
AI科技星2 小时前
《数学公理体系·第三部·数术几何》(2026 年版)
c语言·开发语言·线性代数·算法·矩阵·量子计算·agi
小小编程路3 小时前
C++ 多线程与并发
java·jvm·c++