1.Set
set是一个有序的集合,其中的元素是唯一的,不允许重复(这可以实现并集的操作)。
它基于红黑树实现,因此插入、删除和查找操作都具有较高的效率。没有索引。
元素会按照升序排序,默认情况下,也可以自定义排序规则。
set的主要操作:
下面是set
类的主要操作:
插入元素:可以使用insert()
函数将一个元素插入到set
中,并将其自动排序。
删除元素:可以使用erase()
函数删除
查找元素:可以使用find()
函数来查找指定的元素,返回值是一个指向该元素的迭代器。如果元素不存在,则返回end()
迭代器。
获取元素个数:可以使用size()
函数获取set
中的元素个数。
清空整个set
:可以使用clear()
函数清空整个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 << "Elements in set: ";
for (int i : mySet) {
std::cout << i << " ";
}
std::cout << std::endl;
// 查找元素
int key = 8;
std::set<int>::iterator it = mySet.find(key);
if (it != mySet.end()) {
std::cout << key << " found in set." << std::endl;
} else {
std::cout << key << " not found in set." << std::endl;
}
// 删除元素
mySet.erase(2);
// 遍历并输出所有元素
std::cout << "Elements in set after erasing: ";
for (int i : mySet) {
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
在上面的示例中,我们首先创建了一个空的set容器 `mySet`。然后,我们使用 `insert` 函数插入元素 5、2 和 8。由于set容器中的元素是唯一的,所以重复的元素(如插入的第二个2)不会被插入。
接下来,我们使用范围 `for` 循环遍历并输出所有元素。由于set是有序的,所以输出的元素会按照升序排序。
然后,我们使用 `find` 函数查找元素 8 是否在set中。如果找到了,我们输出该元素存在于set中的信息;如果没有找到,我们输出该元素不存在于set中的信息。
最后,我们使用 `erase` 函数删除元素 2。然后再次遍历并输出所有元素,可以看到元素 2 已经被成功删除。
交集,并集,差集
`set` 支持集合操作,包括交集、并集和差集。可以使用 `set` 的成员函数或算法库中的函数来实现这些操作。
下面是使用 `set` 的成员函数实现集合操作的示例代码:
#include <iostream>
#include <set>
int main() {
std::set<int> set1 = { 1, 2, 3, 4, 5 };
std::set<int> set2 = { 3, 4, 5, 6, 7 };
// 交集
std::set<int> intersection;
for (auto element : set1) {
if (set2.count(element) > 0) {
intersection.insert(element);
}
}
// 并集
std::set<int> unionSet = set1;
unionSet.insert(set2.begin(), set2.end());
// 差集
std::set<int> difference;
for (auto element : set1) {
if (set2.count(element) == 0) {
difference.insert(element);
}
}
// 输出结果
std::cout << "Intersection: ";
for (auto element : intersection) {
std::cout << element << " ";
}
std::cout << std::endl;
std::cout << "Union: ";
for (auto element : unionSet) {
std::cout << element << " ";
}
std::cout << std::endl;
std::cout << "Difference: ";
for (auto element : difference) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
输出结果为:
Intersection: 3 4 5
Union: 1 2 3 4 5 6 7
Difference: 1 2
上述代码中,我们使用了 `count()` 成员函数来判断元素是否存在于另一个集合中。然后,根据判断结果,将元素插入到相应的集合中,从而实现了交集、并集和差集的操作。
除了使用成员函数,还可以使用算法库中的函数来实现集合操作,如 `std::set_intersection()`、`std::set_union()` 和 `std::set_difference()` 等。这些函数的使用方式与上述示例类似,只是需要传入迭代器范围作为参数,并指定输出结果的目标容器。
`std::set_intersection()`、`std::set_union()` 和 `std::set_difference()` 是 C++ 标准库中的算法函数,用于实现集合操作。这些函数位于 `<algorithm>` 头文件中。
下面是使用这些函数实现集合操作的示例代码:
#include <iostream>
#include <algorithm>
#include <set>
int main() {
std::set<int> set1 = { 1, 2, 3, 4, 5 };
std::set<int> set2 = { 3, 4, 5, 6, 7 };
// 交集
std::set<int> intersection;
std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), std::back_inserter(intersection));
// 并集
std::set<int> unionSet;
std::set_union(set1.begin(), set1.end(), set2.begin(), set2.end(), std::back_inserter(unionSet));
// 差集
std::set<int> difference;
std::set_difference(set1.begin(), set1.end(), set2.begin(), set2.end(), std::back_inserter(difference));
// 输出结果
std::cout << "Intersection: ";
for (const auto& element : intersection) {
std::cout << element << " ";
}
std::cout << std::endl;
std::cout << "Union: ";
for (const auto& element : unionSet) {
std::cout << element << " ";
}
std::cout << std::endl;
std::cout << "Difference: ";
for (const auto& element : difference) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}
输出结果与前面的示例相同:
Intersection: 3 4 5
Union: 1 2 3 4 5 6 7
Difference: 1 2
在上述代码中,我们使用了 `std::set_intersection()`、`std::set_union()` 和 `std::set_difference()` 函数来进行集合操作。这些函数接受四个迭代器参数,分别表示两个集合的起始和结束位置。需要注意的是,输出结果需要提供一个目标容器,我们使用 `std::back_inserter()` 来将结果插入到一个 `std::vector` 容器中。
通过使用这些算法函数,我们可以更简洁地实现集合操作,而不需要手动编写循环来遍历集合元素。
2.unorder_set
`unordered_set`是C++标准库中的一个容器,它提供了一种无序、唯一的元素集合。它基于哈希表实现,因此具有快速的插入、查找和删除操作的特点。
与`set`相比,`unordered_set`不会对元素进行排序,而是根据元素的哈希值进行组织和存储。这使得在大多数情况下,`unordered_set`的插入、查找和删除操作的时间复杂度都是常数级别的,即O(1)。
`unordered_set`的常用操作:
下面是unorder_set类的主要操作:
插入元素:可以使用insert()
函数将一个元素插入到unorder_set
中。
删除元素:可以使用erase()
函数删除
查找元素:可以使用find()
函数来查找指定的元素,返回值是一个指向该元素的迭代器。如果元素不存在,则返回end()
迭代器。
获取元素个数:可以使用size()
函数获取set
中的元素个数。
清空整个set
:可以使用clear()
函数清空整个set
。
用一段代码展示unorder_set的主要功能:
#include <iostream>
#include <unordered_set>
int main() {
std::unordered_set<int> mySet;
// 插入元素
mySet.insert(1);
mySet.insert(2);
mySet.insert(3);
// 删除元素
mySet.erase(2);
// 查找元素
auto it = mySet.find(3);
if (it != mySet.end()) {
std::cout << "Found element: " << *it << std::endl;
}
// 遍历元素
for (auto element : mySet) {
std::cout << element << " ";
}
std::cout << std::endl;
// 获取大小和容量
std::cout << "Size: " << mySet.size() << std::endl;
std::cout << "Empty: " << (mySet.empty() ? "true" : "false") << std::endl;
return 0;
}
输出结果:
Found element: 3
1 3
Size: 2
Empty: false
`unordered_set`和`set`
`unordered_set`和`set`是C++标准库中的两种不同的容器,它们在实现方式、性能和用途上有一些区别。
1. 实现方式:
- `unordered_set`:基于哈希表实现,使用哈希函数将元素映射到桶中,具有快速的插入、查找和删除操作。
- `set`:基于红黑树实现,对元素进行排序并保持唯一性,具有自动排序的特性。
2. 元素顺序:
- `unordered_set`:不会对元素进行排序,元素存储的顺序是根据哈希值决定的,因此是无序的。
- `set`:会根据元素的比较函数进行排序,元素存储的顺序是有序的。
3. 插入和查找性能:
- `unordered_set`:插入、查找和删除操作的平均时间复杂度为常数级别O(1),但在最坏情况下可能达到线性级别O(n)。
- `set`:插入、查找和删除操作的平均时间复杂度为对数级别O(log n),保持了较好的性能。
4. 内存占用:
- `unordered_set`:由于使用哈希表,需要额外的内存来存储桶和哈希函数等信息,因此在相同元素数量的情况下,通常会占用更多的内存。
- `set`:由于使用红黑树,不需要额外的内存来存储哈希表等信息,因此在相同元素数量的情况下,通常会占用较少的内存。
3.三元表达式
在之前的代码里,我们用到了三元表达式:
mySet.empty() ? "true" : "false"
在C++中,a?b: c 是三元条件运算符(也称为三元表达式)。它的功能是根据条件 a 的结果来选择执行 b 还是 c。
具体来说,如果条件 a 为真(非零),则表达式的结果为 b;如果条件 a 为假(零),则表达式的结果为 c。因此,三元条件运算符可以看作是一个简洁的if-else语句的缩写形式。
例如,以下代码使用三元条件运算符来比较两个整数的大小,并输出较大的数:
int a = 10;
int b = 20;
int maxNum = (a > b) ? a : b;
std::cout << "The maximum number is: " << maxNum << std::endl;
在上述代码中,如果 a 大于 b,则将 a 的值赋给 maxNum;否则,将 b 的值赋给 maxNum。最后,通过输出语句将结果打印到控制台。