往期汇总:
C++STL(1) vector容器汇总
C++STL(2) list容器汇总
C++STL(3) queue容器汇总
C++STL(4) stack容器汇总
C++STL(5) set容器汇总
C++STL(6) map容器汇总
C++STL(7) unordered_map容器汇总
C++STL(5) set容器汇总
一、绪论
C++中的std::set
是一个容器,它提供了一种有序、不重复元素的集合。以下是关于std::set
容器的一些介绍:
-
有序性:
std::set
中的元素按照升序进行排序,默认情况下使用元素的比较运算符(<
)进行排序。您还可以通过提供自定义的比较函数或比较对象来定义元素的排序方式。 -
唯一性:
std::set
中的元素是唯一的,即集合中不允许重复的元素。当您尝试插入重复的元素时,std::set
会忽略该插入操作。 -
底层实现:
std::set
通常使用红黑树(Red-Black Tree)实现,这是一种高效的自平衡二叉搜索树。红黑树的特性使得插入、删除和查找操作的时间复杂度都是对数时间O(logN),其中N是集合中的元素数量。 -
插入和删除操作:可以使用
std::set
的insert()
函数插入元素,使用erase()
函数删除元素。插入和删除操作会自动维护集合的有序性和唯一性。 -
查找操作:
std::set
提供了高效的查找操作。可以使用find()
函数来查找指定元素,并返回指向该元素的迭代器。此外,std::set
还提供了其他查找函数,如lower_bound()
、upper_bound()
和equal_range()
,用于获取有序集合中符合特定条件的元素。 -
迭代器支持:
std::set
支持正向迭代器和反向迭代器,可以使用迭代器遍历集合中的元素。 -
其他成员函数:除了前面提到的常用操作之外,
std::set
还提供了一些其他的成员函数,如size()
用于获取集合中的元素数量,empty()
用于检查集合是否为空,以及clear()
用于清空集合中的所有元素。
std::set
是C++标准模板库(STL)中非常有用和常用的容器之一。它提供了高效的有序集合操作,并在许多场景下被广泛应用,例如去重操作、元素的存储和查找等。
希望这些介绍能够帮助您理解C++中的std::set
容器。如有任何进一步的问题,请随时提问。
二、构造函数和成员函数
当涉及到C++中的std::set
库的构造函数和成员函数时,以下是一些基本的介绍:
构造函数:
-
默认构造函数:
set< T > mySet;
创建一个空的std::set
对象,其中T是元素类型。 -
范围构造函数:
set< T > mySet(begin, end);
创建一个std::set
对象,并将范围[begin, end)
内的元素复制到新的集合中。 -
拷贝构造函数:
set< T > mySet(otherSet);
创建一个新的std::set
对象,并复制另一个std::set
对象otherSet
中的元素。 -
移动构造函数:
set< T > mySet(std::move(otherSet));
创建一个新的std::set
对象,并使用另一个std::set
对象otherSet
中的元素。在移动构造函数之后,otherSet
将为空。 -
构造函数示例:
#include <iostream>
#include <set>
int main() {
// 默认构造函数创建空的 set
std::set<int> mySet;
// 范围构造函数从数组中创建 set
int arr[] = {5, 2, 8, 1, 9};
std::set<int> mySet2(arr, arr + 5);
// 拷贝构造函数创建 set
std::set<int> mySet3(mySet2);
return 0;
}
成员函数:
-
begin()
和end()
:返回指向std::set
中第一个元素和最后一个元素之后位置的迭代器。 -
size()
和empty()
:size()
返回std::set
中元素的数量,empty()
检查std::set
是否为空。 -
insert(val)
:将值val
插入到std::set
中。如果该值已经存在于集合中,则插入操作将被忽略。 -
erase(val)
:从std::set
中删除值为val
的元素。 -
find(val)
:返回一个指向值为val
的元素的迭代器。如果元素不存在,则返回std::set
的end()
迭代器。 -
count(val)
:返回集合中与val
相等的元素的数量,由于std::set
中的元素是唯一的,因此该函数的返回值只能是0或1。 -
lower_bound(val)
和upper_bound(val)
:lower_bound(val)
返回一个指向第一个不小于val
的元素的迭代器,upper_bound(val)
返回一个指向第一个大于val
的元素的迭代器。 -
clear()
:清空std::set
中的所有元素。
这些是std::set
的一些常用构造函数和成员函数。std::set
还提供了其他一些成员函数,如交集、并集和差集等操作。
请注意,std::set
是C++
的标准库容器之一,因此可以在不同的C++
编译器和环境中使用。具体的用法和语法可以参考C++
的相关文档和资料。
- 成员函数示例:
#include <iostream>
#include <set>
int main() {
std::set<int> mySet = {5, 2, 8, 1, 9};
// 使用 insert 插入元素
mySet.insert(4);
mySet.insert(1); // 重复元素,不会被插入
// 使用 erase 删除元素
mySet.erase(8);
// 使用 find 查找元素
std::set<int>::iterator it = mySet.find(5);
if (it != mySet.end()) {
std::cout << "元素 5 存在于 set 中" << std::endl;
}
// 使用 size 获取元素数量
std::cout << "set 中的元素数量:" << mySet.size() << std::endl;
// 使用迭代器遍历 set
for (auto it = mySet.begin(); it != mySet.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用 clear 清空 set
mySet.clear();
// 检查 set 是否为空
if (mySet.empty()) {
std::cout << "set 是空的" << std::endl;
}
return 0;
}
这些示例展示了std::set
的构造函数和一些常用的成员函数的用法。您可以根据具体的需求和情况使用这些函数来操作和管理std::set
对象中的元素。
三、结语
std::set
作为C++
标准库中的容器之一,具有以下优点和缺点:
优点:
-
元素唯一性:
std::set
中的元素是唯一的,每个元素只能出现一次。这使得std::set
非常适用于需要存储唯一元素的情况。 -
自动排序:
std::set
中的元素按照特定的排序规则自动进行排序。默认情况下,元素按照升序进行排序,但也可以通过自定义比较函数来实现自定义排序。 -
快速查找:
std::set
中的元素是基于红黑树等数据结构实现的,这使得在集合中进行查找操作非常高效。find
函数的时间复杂度为O(logN),其中N是集合中的元素数量。 -
动态扩展:
std::set
是动态扩展的,可以根据需要动态添加或删除元素,而不需要事先知道集合的大小。
缺点:
-
插入和删除的效率较低:由于
std::set
中的元素需要保持有序,因此在插入和删除元素时,可能需要进行树结构的调整,这会导致一些额外的开销。插入和删除的平均时间复杂度为O(logN)。 -
不支持随机访问:由于
std::set
是通过树结构实现的,它不支持像数组一样的随机访问。要访问集合中的特定元素,需要使用迭代器进行顺序访问。 -
额外的内存开销:为了维护元素的唯一性和有序性,
std::set
需要额外的内存来存储和管理树结构。这可能会导致相对较高的内存开销,尤其是在存储大量元素时。 -
不适合频繁修改:由于插入和删除操作的效率较低,
std::set
不适合在需要频繁修改集合的情况下使用。如果需要频繁修改集合,可能需要考虑其他数据结构,如std::unordered_set
。
综上所述,std::set
在元素唯一性、自动排序和快速查找方面具有优势,但在插入和删除效率、随机访问和内存开销方面存在一些限制。因此,在选择数据结构时,需要根据具体的需求和场景来权衡这些优点和缺点。