std::set
和 std::unordered_set
都是 C++ 标准模板库(STL)中的关联容器,用于存储不重复的元素。它们的具体区别和联系如下:
- 底层实现:
-
std::set
使用红黑树(Red-Black Tree)实现,因此元素是有序的,插入、删除和查找操作的时间复杂度为 O(log n)。 -
std::unordered_set
使用哈希表(Hash Table)实现,因此元素的存储顺序不确定,插入、删除和查找操作的平均时间复杂度为 O(1),但最坏情况下可能达到 O(n)。
- 元素顺序:
-
std::set
中的元素是有序的,按照键的自然顺序进行排序(默认情况下为升序)。 -
std::unordered_set
中的元素是无序的,元素的存储顺序取决于哈希函数的值。
- 查找性能:
- 在
std::set
中进行查找操作时,因为元素是有序的,可以使用二分查找,因此查找操作的时间复杂度为 O(log n)。 - 在
std::unordered_set
中进行查找操作时,使用哈希表实现,平均情况下查找操作的时间复杂度为 O(1)。
- 内存占用:
-
std::set
在存储元素时,除了元素本身外,还需要额外的内存来存储树结构,因此相比于std::unordered_set
,它通常会占用更多的内存。 -
std::unordered_set
在存储元素时,只需要考虑哈希表的大小和负载因子,因此通常情况下占用的内存相对较少。
- 迭代器稳定性:
- 在
std::set
中,迭代器的稳定性是保证的,即在插入或删除元素后仍然有效。 - 在
std::unordered_set
中,由于哈希表的结构,插入或删除元素可能导致重新哈希,因此迭代器的稳定性可能会受到影响。
综上所述,选择 std::set
还是 std::unordered_set
取决于具体的需求。如果需要有序存储且查找性能要求不高,或者需要保证迭代器稳定性,则可以选择 std::set
。如果对元素顺序没有特殊要求,但需要较快的查找性能和较少的内存占用,则可以选择 std::unordered_set
。
#include <iostream>
#include <set>
#include <unordered_set>
using namespace std;
int main() {
// 使用 std::set 存储不重复的元素,元素是有序的
set<int> orderedSet;
// 使用 std::unordered_set 存储不重复的元素,元素是无序的
unordered_set<int> unorderedSet;
// 插入元素
orderedSet.insert(3);
orderedSet.insert(1);
orderedSet.insert(4);
orderedSet.insert(2);
unorderedSet.insert(3);
unorderedSet.insert(1);
unorderedSet.insert(4);
unorderedSet.insert(2);
// 输出有序集合的元素
cout << "Ordered set elements: ";
for (int num : orderedSet) {
cout << num << " ";
}
cout << endl;
// 输出无序集合的元素
cout << "Unordered set elements: ";
for (int num : unorderedSet) {
cout << num << " ";
}
cout << endl;
// 查找元素
if (orderedSet.find(3) != orderedSet.end()) {
cout << "3 exists in ordered set" << endl;
} else {
cout << "3 does not exist in ordered set" << endl;
}
if (unorderedSet.find(3) != unorderedSet.end()) {
cout << "3 exists in unordered set" << endl;
} else {
cout << "3 does not exist in unordered set" << endl;
}
return 0;
}