#include <iostream>
#include <set>
#include <unordered_set>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
struct Person {
std::string name;
int age;
Person() = default;
Person(const std::string& n, int a) : name(n), age(a) {}
bool operator<(const Person& other) const {
if (age != other.age) return age < other.age;
return name < other.name;
}
};
struct Descending {
bool operator()(int a, int b) const {
return a > b;
}
};
int main() {
std::cout << "========== std::set basic operations ==========\n";
std::set<int> s1;
std::set<int, Descending> s2;
std::set<int> s3 = {5, 2, 8, 2, 1, 9};
std::set<int> s4(s3.begin(), s3.end());
std::set<int> s5(s3);
s1.insert(10);
s1.insert(5);
s1.insert(20);
s1.insert(5);
auto [pos, inserted] = s1.insert(15);
std::cout << "Insert 15 " << (inserted ? "succeeded" : "failed") << '\n';
std::vector<int> vec = {30, 25, 30};
s1.insert(vec.begin(), vec.end());
s1.insert({40, 35, 40});
s1.emplace(45);
s1.emplace_hint(s1.end(), 50);
std::cout << "s1 contents (ascending): ";
for (int x : s1) std::cout << x << " ";
std::cout << '\n';
size_t n = s1.erase(30);
std::cout << "Erase 30: " << (n ? "succeeded" : "failed") << '\n';
auto it = s1.find(40);
if (it != s1.end()) {
s1.erase(it);
std::cout << "Erased 40\n";
}
auto first = s1.lower_bound(20);
auto last = s1.upper_bound(35);
s1.erase(first, last);
std::cout << "After erasing elements in [20,35), s1: ";
for (int x : s1) std::cout << x << " ";
std::cout << '\n';
s1.clear();
std::cout << "After clearing s1 size: " << s1.size() << '\n';
std::set<int> ss = {1, 2, 3, 4, 5};
auto it_find = ss.find(3);
if (it_find != ss.end()) std::cout << "Found " << *it_find << '\n';
std::cout << "count of element 3: " << ss.count(3) << '\n';
#if __cplusplus >= 202002L
if (ss.contains(4)) std::cout << "contains(4) is true\n";
#endif
std::set<int> bounds = {10, 20, 30, 40, 50};
auto low = bounds.lower_bound(25);
auto up = bounds.upper_bound(35);
std::cout << "lower_bound(25): " << *low << '\n';
std::cout << "upper_bound(35): " << *up << '\n';
auto eq = bounds.equal_range(30);
std::cout << "equal_range(30): [" << *eq.first << ", " << *eq.second << "]\n";
std::set<int> sz = {1,2,3};
std::cout << "size: " << sz.size() << '\n';
std::cout << "empty: " << std::boolalpha << sz.empty() << '\n';
std::cout << "max_size: " << sz.max_size() << " (platform-dependent)\n";
std::set<int> iter_set = {10,20,30,40};
std::cout << "Forward iteration: ";
for (auto it = iter_set.begin(); it != iter_set.end(); ++it) std::cout << *it << " ";
std::cout << "\nReverse iteration: ";
for (auto rit = iter_set.rbegin(); rit != iter_set.rend(); ++rit) std::cout << *rit << " ";
std::cout << "\nRange for: ";
for (int x : iter_set) std::cout << x << " ";
std::cout << '\n';
std::set<int, Descending> comp_set = {5,2,8,1};
auto key_comp = comp_set.key_comp();
std::cout << "In descending set, is first element less than second? " << key_comp(5,2) << " (5>2 returns false)\n";
auto val_comp = comp_set.value_comp();
(void)val_comp;
std::set<int> a = {1,2,3}, b = {4,5,6};
a.swap(b);
std::cout << "After swap a: "; for(int x:a) std::cout << x << " ";
std::cout << ", b: "; for(int x:b) std::cout << x << " ";
std::cout << '\n';
std::set<Person> people;
people.insert(Person("Alice", 25));
people.insert(Person("Bob", 30));
people.insert(Person("Charlie", 22));
people.emplace("David", 25);
std::cout << "Person set (sorted by age): ";
for (const auto& p : people) std::cout << p.name << "(" << p.age << ") ";
std::cout << '\n';
std::cout << "\n========== std::multiset (allows duplicates) ==========\n";
std::multiset<int> ms = {1, 2, 2, 3, 3, 3};
ms.insert(2);
ms.insert(4);
std::cout << "multiset contents: ";
for (int x : ms) std::cout << x << " ";
std::cout << '\n';
std::cout << "count of 2: " << ms.count(2) << '\n';
ms.erase(3);
std::cout << "After erasing all 3: ";
for (int x : ms) std::cout << x << " ";
std::cout << '\n';
auto it_ms = ms.find(2);
if (it_ms != ms.end()) std::cout << "find found: " << *it_ms << '\n';
ms = {1,2,2,2,3,4,5};
auto lo = ms.lower_bound(2);
auto up_ms = ms.upper_bound(2);
std::cout << "lower_bound(2): " << *lo << ", upper_bound(2): " << *up_ms << '\n';
auto eq_ms = ms.equal_range(2);
std::cout << "equal_range(2) range length: " << std::distance(eq_ms.first, eq_ms.second) << '\n';
std::cout << "\n========== std::unordered_set (hash, unordered) ==========\n";
std::unordered_set<int> us = {5, 2, 8, 2, 1, 9, 5};
us.insert(10);
us.emplace(7);
std::cout << "unordered_set contents (unordered): ";
for (int x : us) std::cout << x << " ";
std::cout << '\n';
std::cout << "bucket_count: " << us.bucket_count() << '\n';
std::cout << "load_factor: " << us.load_factor() << '\n';
auto it_us = us.find(8);
if (it_us != us.end()) std::cout << "Found 8\n";
us.erase(2);
std::cout << "After erasing 2: ";
for (int x : us) std::cout << x << " ";
std::cout << '\n';
struct PersonHash {
std::size_t operator()(const Person& p) const {
return std::hash<std::string>()(p.name) ^ (std::hash<int>()(p.age) << 1);
}
};
struct PersonEqual {
bool operator()(const Person& a, const Person& b) const {
return a.name == b.name && a.age == b.age;
}
};
std::unordered_set<Person, PersonHash, PersonEqual> us_person;
us_person.insert(Person("Alice", 25));
us_person.insert(Person("Bob", 30));
us_person.insert(Person("Alice", 25));
std::cout << "unordered_set<Person> size: " << us_person.size() << '\n';
std::cout << "\n========== Set operations (union, intersection, difference) ==========\n";
std::set<int> A = {1, 2, 3, 4, 5};
std::set<int> B = {4, 5, 6, 7, 8};
std::set<int> result;
std::set_union(A.begin(), A.end(), B.begin(), B.end(),
std::inserter(result, result.begin()));
std::cout << "A ∪ B: ";
for (int x : result) std::cout << x << " ";
std::cout << '\n';
result.clear();
std::set_intersection(A.begin(), A.end(), B.begin(), B.end(),
std::inserter(result, result.begin()));
std::cout << "A ∩ B: ";
for (int x : result) std::cout << x << " ";
std::cout << '\n';
result.clear();
std::set_difference(A.begin(), A.end(), B.begin(), B.end(),
std::inserter(result, result.begin()));
std::cout << "A - B: ";
for (int x : result) std::cout << x << " ";
std::cout << '\n';
result.clear();
std::set_symmetric_difference(A.begin(), A.end(), B.begin(), B.end(),
std::inserter(result, result.begin()));
std::cout << "A △ B: ";
for (int x : result) std::cout << x << " ";
std::cout << '\n';
std::cout << "\n========== Other advanced operations ==========\n";
std::set<int>::allocator_type alloc = s3.get_allocator();
int* p = alloc.allocate(1);
alloc.construct(p, 42);
std::cout << "Value constructed by allocator: " << *p << '\n';
alloc.destroy(p);
alloc.deallocate(p, 1);
std::set<int> source = {100, 200};
std::set<int> target = {300};
auto node = source.extract(100);
if (node) {
target.insert(std::move(node));
std::cout << "After extracting and inserting, target contains 100: " << (target.find(100) != target.end()) << '\n';
}
source = {400, 500};
target.merge(source);
std::cout << "After merge target size: " << target.size() << ", source size: " << source.size() << '\n';
return 0;
}