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()可避免不必要的拷贝
相关推荐
破茧蝴蝶2 小时前
Python分布式爬虫完整教程
开发语言·python
狗凯之家源码网3 小时前
全新 PHP 轻量客服聊天室源码深度评测
开发语言·php·聊天室系统
远离UE43 小时前
UE5 Substrate Thin Film 源码拆析
开发语言·javascript·ue5
keyipatience3 小时前
JavaScript学习(1)书写位置,变量、数据类型、运算符
开发语言·前端·javascript·css·学习
一拳一个呆瓜4 小时前
【STL】文件系统导航
c++·stl
All for pursuit.4 小时前
【动态规划-21】312.戳气球
数据结构·c++·算法·leetcode·动态规划
栈帧之外4 小时前
【C++】STL之set
开发语言·c++
catchadmin5 小时前
免费可商用 PHP 管理后台 CatchAdmin V5.4.1 发布,新增 MCP 支持
开发语言·php
zhanghaha13145 小时前
C++构造函数的一些其他应用(逐词逐句保姆讲解)
c++
jimy16 小时前
c++的 Type Traits (二、更详细版本)
开发语言·c++