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()可避免不必要的拷贝
相关推荐
weixin_462446239 小时前
使用 Python 创建和导出 Jupyter Notebook:从零到一的完整教程
开发语言·python·jupyter
苦藤新鸡9 小时前
9.找到字符串中所有字母异位词
数据结构·c++·算法·力扣
令狐掌门10 小时前
C++ io_uring介绍
c++·io_uring
蕨蕨学AI10 小时前
【Wolfram语言】44 导入与导出
开发语言·wolfram
豆沙沙包?10 小时前
2026年--Lc336-1448. 统计二叉树中好节点的数目(树)--java版
java·开发语言·深度优先
青小莫10 小时前
C++之类和对象(下)
java·开发语言·c++
superman超哥10 小时前
惰性求值(Lazy Evaluation)机制:Rust 中的优雅与高效
开发语言·后端·rust·编程语言·lazy evaluation·rust惰性求值
Wiktok10 小时前
关于Python继承和super()函数的问题
java·开发语言
liulilittle10 小时前
rinetd 端口转发工具技术原理
linux·服务器·网络·c++·端口·通信·转发