【C++ STL】set容器的基本使用

set容器

set 是 C++ STL 中实现有序集合的关联式容器 ,底层基于红黑树(平衡二叉搜索树)实现,核心特性是:元素唯一且自动按升序排序,不支持随机访问,插入 / 删除 / 查找操作的时间复杂度均为 O(logn)。 特征:

  • 底层实现:红黑树(一种自平衡的二叉搜索树),保证元素有序且操作高效。
  • 核心特性
    • 元素不可重复 (自动去重),若需允许重复元素,使用 multiset
    • 元素自动升序排序 (默认按 < 比较,也可自定义排序规则);
    • 不支持直接修改元素(需先删除旧值,再插入新值);
    • 支持迭代器遍历,迭代器为双向迭代器(无 []at() 随机访问)。

基本使用

  • 使用 set 必须包含头文件
c++ 复制代码
#include <set> // 核心头文件
  • 初始化
c++ 复制代码
// 1、默认构造函数,空set(默认升序排列)
set<int> s1;

// 2、初始化列表(c++ 11)
set<int> s2 = { 5, 7, 1, 1, 3, 9 };	// 自动去重 + 升序排列
for (set<int>::iterator it = s2.begin(); it != s2.end(); it++)
{
	cout << *it << " ";		// 输出1 3 5 7 9
}
cout << endl;

// 3、范围构造,从其他容器/迭代器范围初始化
set<int> s3(++s2.begin(), --s2.end());
for (set<int>::iterator it = s3.begin(); it != s3.end(); it++)
{
	cout << *it << " ";		// 输出 3 5 7 
}
cout << endl;

// 4、自定义排序规则(降序)
set<int, greater<int>> s4 = { 3, 5, 7, 9 };
for (set<int>::iterator it = s4.begin(); it != s4.end(); it++)
{
	cout << *it << " ";		// 输出 9 7 5 3 
}
cout << endl;

// 5、拷贝构造
set<int> s5(s3);

核心操作API

  • empty()判断 set 是否为空,返回 bool(空为 true)
  • size()返回元素个数(unsigned int 类型)
  • insert(val)插入元素 val,返回 pair<iterator, bool>:bool 表示是否插入成功(重复则失败)

! 说明\] `pair` 是 C++ STL 中 `set`/`map` 等关联式容器的 `insert()`/`emplace()` 函数的**返回值类型**,本质是一个「成对的数据结构」,用来同时返回两个信息:插入操作的结果(是否成功)+ 插入 / 找到的元素的迭代器。 * `first`:存储第一个数据(对应 `set` 插入时的「迭代器」); * `second`:存储第二个数据(对应 `set` 插入时的「是否成功」)。

c++ 复制代码
set<int> s1 = { 5, 7, 1, 1, 3, 9 };

// 插入元素
pair<set<int>::iterator, bool> ret1 = s1.insert(10);
pair<set<int>::iterator, bool> ret2 = s1.insert(1);

for (set<int>::iterator it = s1.begin(); it != s1.end(); it++)
{
	cout << *it << " ";
}
cout << endl;

cout << *ret1.first << endl;	// 10
cout << ret1.second << endl;	// 1

cout << *ret2.first << endl;	// 1
cout << ret2.second << endl;	// 0
  • emplace(val)直接构造元素(效率高于 insert),返回值同 insert
  • erase(pos)删除迭代器 pos 指向的元素
  • erase(val)删除值为 val 的元素,返回删除的个数(set 中只能是 0 或 1)
c++ 复制代码
set<int> s1 = { 5, 7, 1, 1, 3, 9 };

int ret = s1.erase(9);
cout << ret << endl;	// 1
  • erase(beg, end)删除 [beg, end) 范围内的元素
  • clear()清空所有元素find(val)查找值为 val 的元素,返回迭代器:找到则指向该元素,否则指向 end()
  • count(val)统计值为 val 的元素个数(set 中只能是 0 或 1)
  • lower_bound(val)返回第一个 ≥ val 的元素的迭代器
  • upper_bound(val)返回第一个 > val 的元素的迭代器
  • swap(s)交换两个同类型 set 的内容

进阶用法

  • 自定义排序规则
C++ 复制代码
// 自定义降序比较器 
struct MyCompare { 
	bool operator()(int a, int b) const 
	{ 
		return a > b; // 降序排序 
	} 
};

int main() 
{ 
	set<int, MyCompare> s = {5,2,8,1}; // 自定义排序 → {8,5,2,1} cout << "降序遍历:"; 
	for (int num : s) 
	{ 
		cout << num << " "; // 输出:8 5 2 1 } 
		return 0; 
	}
  • 存储自定义数据类型(需要重载比较运算符)

! 注意\] 若 `set` 存储自定义结构体 / 类,必须重载 `<` 运算符(或自定义比较器),否则无法排序; 如果需要自定义数据类型按照降序排列,秩序要该return id \> other.id; // 按学号降序

c++ 复制代码
#include <iostream>
#include <set>
#include <string>
using namespace std;

// 自定义结构体:学生(按学号升序排序)
struct Student {
    int id;
    string name;
    // 重载 < 运算符,指定排序规则
    bool operator<(const Student& other) const {
        return id < other.id;  // 按学号升序
    }
};

int main() {
    set<Student> s;
    s.insert({ 2, "Lily" });
    s.insert({ 1, "Tom" });
    s.insert({ 3, "Jack" });

    // 遍历:按学号升序输出
    for (const auto& stu : s) {
        cout << "学号:" << stu.id << ",姓名:" << stu.name << endl;
    }
    return 0;
}
  • multiset(允许重复元素) multisetset 用法几乎一致,唯一区别是允许元素重复,核心差异:
  • insert() 始终返回迭代器(无 bool 值);
  • count(val) 可返回大于 1 的数;
  • erase(val) 会删除所有值为 val 的元素。

注意事项

  • 元素不可修改set 的迭代器是 const_iterator(即使写 iterator,也无法修改元素),因为修改元素会破坏红黑树的有序性。若需修改,需先删除旧值,再插入新值;
  • 查找效率find()count() 更高效(find() 找到即返回,count() 需统计个数),判断元素是否存在优先用 find()
  • 迭代器稳定性:插入 / 删除元素时,除被删除元素的迭代器外,其他迭代器仍有效(红黑树特性)。
  • 空 set 的 end ()find() 找不到元素时返回 end(),不可解引用(*s.end() 会崩溃)。

总结语

  • set 是基于红黑树的有序集合,元素唯一且自动升序,操作复杂度 O(logn),无随机访问;
  • 核心操作:insert()/emplace()(插入)、erase()(删除)、find()(查找)、clear()(清空),遍历仅支持双向迭代器;
  • 自定义类型需重载 < 运算符,允许重复元素用 multiset,修改元素需先删后插。
相关推荐
IT老小子3 小时前
【C++ STL】queue队列容器的基本使用
编程语言
桦说编程20 小时前
你的函数什么颜色?—— 深入理解异步编程的本质问题(上)
后端·性能优化·编程语言
codetown4 天前
C3 编程语言:现代系统级开发的演进与工程实践全指南
编程语言
IT老小子4 天前
【C++STL】Vector的使用(1)
编程语言
会员源码网6 天前
尝试修改常量值(`Fatal error: Cannot re-assign auto-global variable _POST`)
编程语言·代码规范
怕浪猫6 天前
第21章:微服务与分布式架构中的Go应用
后端·go·编程语言
怕浪猫8 天前
第20章:Web服务实战——构建RESTful API
后端·go·编程语言
Arjun11 天前
C语言基础内容整理
编程语言
怕浪猫11 天前
第19章:Go语言工具链与工程实践
后端·go·编程语言