目录
一、描述
std::set 是 C++ STL 中的一个关联容器,用于存储唯一的元素,并且这些元素是按照某种顺序排列的(默认情况下是升序)。std::set 内部通常实现为红黑树,因此插入、删除和查找操作的时间复杂度都是 O(log n)。
基本特性
- 唯一性:每个元素只能出现一次。
- 有序性:元素按某种顺序排列,默认为升序。
- 迭代器:提供双向迭代器,可以从前向后或从后向前遍历元素。
二、创建和初始化
set 是一个模板类,定义在 <set> 头文件中。它的元素是按严格弱序(即使用 < 运算符)排序的。set 默认使用 std::less<T> 作为比较函数对象,但你可以通过传递自定义的比较函数对象来定义排序方式
如:std::set<int, std::greater<int>> mySet; // 降序排列
#include <set>
#include <iostream>
int main()
{
std::set<int> mySet; // 创建一个空的 set
// 初始化 set
std::set<int> anotherSet = {1, 3, 5, 7, 9};
// 输出 set 中的元素
for (int elem : anotherSet)
{
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
三、插入元素
使用 insert 成员函数插入元素。如果元素已经存在,则插入操作不会改变集合
mySet.insert(10);
mySet.insert(20);
mySet.insert(10); // 重复插入,集合不会改变
#include <set>
#include <iostream>
int main()
{
std::set<int> mySet;
// 插入元素
mySet.insert(10);
mySet.insert(20);
mySet.insert(30);
// 插入重复元素(不会插入)
mySet.insert(10);
// 输出 set 中的元素
for (int elem : mySet)
{
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
四、删除元素
使用 erase 成员函数删除元素。可以通过值或迭代器删除
#include <set>
#include <iostream>
int main()
{
std::set<int> mySet = {10, 20, 30, 40, 50};
// 删除指定元素
mySet.erase(30);
// 删除范围内的元素
mySet.erase(mySet.begin(), mySet.find(40));
// 输出 set 中的元素
for (int elem : mySet)
{
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
五、查找元素
使用 find 成员函数查找元素。如果找到,返回指向该元素的迭代器;否则,返回 end()。
#include <set>
#include <iostream>
int main()
{
std::set<int> mySet = {10, 20, 30, 40, 50};
// 查找元素
auto it = mySet.find(30);
if (it != mySet.end())
{
std::cout << "Element found: " << *it << std::endl;
}
else
{
std::cout << "Element not found" << std::endl;
}
return 0;
}
六、遍历元素
由于 set 中的元素是排序的,你可以使用迭代器来访问元素。set 提供的迭代器是双向迭代器。
也可以使用新特性进行遍历
for (const auto& data : mySet)
{
cout << data << endl;
}
#include <set>
#include <iostream>
int main()
{
std::set<int> mySet = {10, 20, 30, 40, 50};
// 使用范围 for 循环遍历
for (int elem : mySet)
{
std::cout << elem << " ";
}
std::cout << std::endl;
// 使用迭代器遍历
for (auto it = mySet.begin(); it != mySet.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
七、大小和空判断
使用 size 和 empty 成员函数
- size():返回 set 中的元素数量。
- empty():检查 set 是否为空。
- clear():清除 set 中的所有元素。
- count():检查 set 中是否存在某个元素(返回 0 或 1)。
std::cout << "Size: " << mySet.size() << std::endl;
if (mySet.empty())
{
std::cout << "Set is empty" << std::endl;
}
八、迭代器
set 提供了 begin、end、rbegin 和 rend 成员函数来返回迭代器。
for (auto it = mySet.rbegin(); it != mySet.rend(); ++it)
{
std::cout << *it << " ";
}
九、自定义比较函数
std::set 可以接受自定义的比较函数,以便按照特定的顺序存储元素。
#include <set>
#include <iostream>
#include <string>
struct CompareLength {
bool operator()(const std::string& a, const std::string& b) const
{
return a.length() < b.length();
}
};
int main()
{
std::set<std::string, CompareLength> mySet;
mySet.insert("short");
mySet.insert("longer");
mySet.insert("medium");
// 输出 set 中的元素
for (const auto& elem : mySet)
{
std::cout << elem << " ";
}
std::cout << std::endl;
return 0;
}
十、其他函数
- clear(): 清除所有元素。
- count(const T& value) const: 返回值为 value 的元素的个数(对于 set 来说,最多为 1)。
- lower_bound(const T& value) const: 返回指向第一个不小于 value 的元素的迭代器。
- upper_bound(const T& value) const: 返回指向第一个大于 value 的元素的迭代器。
- equal_range(const T& value) const: 返回一个 pair,包含 lower_bound 和 upper_bound 的结果。
十一、注意事项
- 唯一性:set 中的元素是唯一的,如果尝试插入一个已存在的元素,插入操作将失败。
- 排序:set 中的元素是按顺序存储的,默认是升序。你可以通过传递自定义的比较函数对象来改变排序方式。
- 迭代器失效:在 set 中插入或删除元素时,指向这些元素的迭代器会失效。因此,不要在插入或删除元素后继续使用旧的迭代器。
示例代码
以下是一个完整的示例代码,展示了如何使用 set:
#include <iostream>
#include <set>
int main()
{
std::set<int> mySet;
// 插入元素
mySet.insert(5);
mySet.insert(2);
mySet.insert(8);
mySet.insert(2); // 重复插入
// 访问元素
std::cout << "Set elements: ";
for (auto it = mySet.begin(); it != mySet.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 查找元素
auto it = mySet.find(8);
if (it != mySet.end())
{
std::cout << "Found: " << *it << std::endl;
}
// 删除元素
mySet.erase(2);
std::cout << "After erase 2: ";
for (auto it = mySet.begin(); it != mySet.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << std::endl;
// 检查大小和是否为空
std::cout << "Size: " << mySet.size() << std::endl;
if (mySet.empty())
{
std::cout << "Set is empty" << std::endl;
}
return 0;
}