本文将详细解析C++ STL中的set
容器,通过代码示例讲解其核心操作和查找方法。set
是一个非常有用的关联容器,它存储唯一的元素,并且元素会自动排序。
1. set容器的基本特性
set
容器具有以下关键特性:
- 唯一性:所有元素都是唯一的,不允许重复
- 自动排序:元素插入后会自动按照升序排列
- 基于红黑树:底层实现通常为红黑树,提供高效的查找、插入和删除操作
2. 头文件与基本使用
使用set
需要包含头文件:
#include <set>
声明一个set
:
set<int> setInt; // 创建一个存储int类型的set
3. 插入元素
使用insert()
方法添加元素:
setInt.insert(1);
setInt.insert(2);
setInt.insert(3);
setInt.insert(4);
setInt.insert(5);
插入后,元素会自动按升序排列。
4. 查找操作
4.1 find()
方法
find(elem)
查找指定元素,返回指向该元素的迭代器:
set<int>::iterator it1 = setInt.find(4);
if (it1 != setInt.end()) {
int elem = *it1; // 解引用迭代器获取元素值
cout << elem << endl; // 输出: 4
} else {
cout << "元素不存在" << endl;
}
重要提示:在使用find()
返回的迭代器前,必须检查它是否等于end()
,否则可能访问无效内存。
4.2 count()
方法
count(elem)
返回容器中值为elem
的元素个数:
int iCount = setInt.count(3);
cout << "count(3)=" << iCount << endl; // 输出: 1 (因为set中元素唯一)
对于set
,返回值只能是0或1;对于multiset
,返回值可能大于1。
5. 边界查找
5.1 lower_bound()
lower_bound(elem)
返回第一个大于等于elem
元素的迭代器:
set<int>::iterator it2 = setInt.lower_bound(3);
int elem2 = *it2;
cout << "lower_bound(3)=" << elem2 << endl; // 输出: 3
5.2 upper_bound()
upper_bound(elem)
返回第一个大于elem
元素的迭代器:
set<int>::iterator it3 = setInt.upper_bound(3);
int elem3 = *it3;
cout << "upper_bound(3)=" << elem3 << endl; // 输出: 4
6. equal_range()
方法
equal_range(elem)
返回一个pair
,包含两个迭代器:
first
:指向第一个不小于elem
的元素(即lower_bound
)second
:指向第一个大于elem
的元素(即upper_bound
)
pair<set<int>::iterator, set<int>::iterator> ii = setInt.equal_range(3);
cout << "equal_range(3) 返回迭代器的第一个值:" << *(ii.first) << endl; // 输出: 3
cout << "equal_range(3) 返回迭代器的第二个值:" << *(ii.second) << endl; // 输出: 4
7. 注意事项
- 迭代器有效性:在修改
set
后,所有迭代器可能失效 - 元素唯一性:尝试插入重复元素不会改变
set
内容 - 性能:查找、插入和删除操作的时间复杂度都是O(log n)
- 内存:由于基于红黑树,内存开销比连续容器大
8. 实际应用场景
set
非常适合以下场景:
- 需要快速查找元素是否存在
- 需要自动排序且元素唯一
- 需要频繁进行集合操作(并集、交集等)
9. 完整代码回顾
#include <iostream>
#include <set>
using namespace std;
int main(void) {
set<int> setInt;
// 插入元素
setInt.insert(1);
setInt.insert(2);
setInt.insert(3);
setInt.insert(4);
setInt.insert(5);
// 查找元素
set<int>::iterator it1 = setInt.find(8);
if (it1 != setInt.end()) {
int elem = *it1;
cout << elem << endl;
} else {
cout << "不存在8" << endl;
}
// 计数
int iCount = setInt.count(3);
cout << "count(3)=" << iCount << endl;
// 边界查找
set<int>::iterator it2 = setInt.lower_bound(3);
set<int>::iterator it3 = setInt.upper_bound(3);
int elem2 = *it2;
int elem3 = *it3;
cout << "lower_bound(3)=" << elem2 << endl;
cout << "upper_bound(3)=" << elem3 << endl;
// 范围查找
pair<set<int>::iterator, set<int>::iterator> ii = setInt.equal_range(3);
cout << "equal_range(3) 返回迭代器的第一个值:" << *(ii.first) << endl;
cout << "equal_range(3) 返回迭代器的第二个值:" << *(ii.second) << endl;
system("pause");
return 0;
}
set
最适合需要快速查找和自动排序的场景,但对于需要频繁随机访问的场景,可能需要考虑其他容器。