std::set


STL container: std::set

std::set is a container in the C++ Standard Template Library (STL) that stores unique elements in a sorted order. It is implemented as a balanced binary search tree, typically a red-black tree, which ensures logarithmic time complexity for insertion, deletion, and search operations.

Key Characteristics

Example 1: Basic Usage

#include <iostream>
#include <set>
#include <string>

int main() {
    std::set<int> numbers = {5, 2, 8, 1, 9, 3, 7};

    // Inserting elements
    numbers.insert(4);
    numbers.insert(6);
    numbers.insert(2); // Duplicate, won't be inserted

    // Printing the set
    std::cout << "Numbers in the set:" << std::endl;
    for (const auto& num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // Checking if an element exists
    if (numbers.find(5) != numbers.end()) {
        std::cout << "5 is in the set" << std::endl;
    }

    // Removing an element
    numbers.erase(3);

    // Size of the set
    std::cout << "Number of elements: " << numbers.size() << std::endl;

    return 0;
}

Explanation:

Example 2: Custom Comparator

#include <iostream>
#include <set>
#include <string>

struct Person {
    std::string name;
    int age;

    bool operator<(const Person& other) const {
        return age < other.age;
    }
};

// Custom comparator for descending order
struct PersonComparator {
    bool operator()(const Person& a, const Person& b) const {
        return a.age > b.age;
    }
};

int main() {
    std::set<Person, PersonComparator> people;

    people.insert({"Alice", 30});
    people.insert({"Bob", 25});
    people.insert({"Charlie", 35});
    people.insert({"David", 28});

    for (const auto& person : people) {
        std::cout << person.name << ": " << person.age << std::endl;
    }

    return 0;
}

Explanation:

Example 3: Set Operations

#include <iostream>
#include <set>
#include <algorithm>

void printSet(const std::set<int>& s, const std::string& name) {
    std::cout << name << ": ";
    for (int num : s) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
}

int main() {
    std::set<int> set1 = {1, 2, 3, 4, 5};
    std::set<int> set2 = {4, 5, 6, 7, 8};

    printSet(set1, "Set 1");
    printSet(set2, "Set 2");

    // Union
    std::set<int> unionSet;
    std::set_union(set1.begin(), set1.end(), set2.begin(), set2.end(), 
                   std::inserter(unionSet, unionSet.begin()));
    printSet(unionSet, "Union");

    // Intersection
    std::set<int> intersectionSet;
    std::set_intersection(set1.begin(), set1.end(), set2.begin(), set2.end(), 
                          std::inserter(intersectionSet, intersectionSet.begin()));
    printSet(intersectionSet, "Intersection");

    // Difference (set1 - set2)
    std::set<int> differenceSet;
    std::set_difference(set1.begin(), set1.end(), set2.begin(), set2.end(), 
                        std::inserter(differenceSet, differenceSet.begin()));
    printSet(differenceSet, "Difference (set1 - set2)");

    // Symmetric Difference
    std::set<int> symDifferenceSet;
    std::set_symmetric_difference(set1.begin(), set1.end(), set2.begin(), set2.end(), 
                                  std::inserter(symDifferenceSet, symDifferenceSet.begin()));
    printSet(symDifferenceSet, "Symmetric Difference");

    return 0;
}

Explanation:

Example 4: Performance Comparison with std::unordered_set

#include <iostream>
#include <set>
#include <unordered_set>
#include <chrono>
#include <random>

template<typename Func>
long long measureTime(Func func) {
    auto start = std::chrono::high_resolution_clock::now();
    func();
    auto end = std::chrono::high_resolution_clock::now();
    return std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
}

int main() {
    const int NUM_ELEMENTS = 1000000;
    const int NUM_SEARCHES = 10000;

    std::set<int> orderedSet;
    std::unordered_set<int> unorderedSet;

    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(1, NUM_ELEMENTS);

    // Insertion
    auto insertOrdered = [&]() {
        for (int i = 0; i < NUM_ELEMENTS; ++i) {
            orderedSet.insert(dis(gen));
        }
    };
    auto insertUnordered = [&]() {
        for (int i = 0; i < NUM_ELEMENTS; ++i) {
            unorderedSet.insert(dis(gen));
        }
    };

    std::cout << "Insertion time (microseconds):" << std::endl;
    std::cout << "set: " << measureTime(insertOrdered) << std::endl;
    std::cout << "unordered_set: " << measureTime(insertUnordered) << std::endl;

    // Search
    auto searchOrdered = [&]() {
        for (int i = 0; i < NUM_SEARCHES; ++i) {
            orderedSet.find(dis(gen));
        }
    };
    auto searchUnordered = [&]() {
        for (int i = 0; i < NUM_SEARCHES; ++i) {
            unorderedSet.find(dis(gen));
        }
    };

    std::cout << "Search time (microseconds):" << std::endl;
    std::cout << "set: " << measureTime(searchOrdered) << std::endl;
    std::cout << "unordered_set: " << measureTime(searchUnordered) << std::endl;

    return 0;
}

Explanation:

Additional Considerations

  1. Iterator Stability: Iterators and references to elements in a set remain valid after insertion or deletion of other elements.

  2. Memory Overhead: set typically has higher memory overhead compared to unordered_set due to the balanced tree structure.

  3. Ordered Operations: set provides efficient operations for finding the next or previous element, which is not possible with unordered_set.

  4. No Direct Element Modification: Elements in a set cannot be modified directly through iterators to maintain the correct ordering.

Summary

std::set is a versatile container in C++ for storing unique elements in a sorted order. Key points to remember:

std::set is particularly useful in situations where you need to maintain a sorted collection of unique elements, perform range-based queries, or when the order of elements is important. It's commonly used in implementing algorithms that require ordered data, maintaining sorted lists of items, and in scenarios where both uniqueness and order are crucial.

Related

Previous Page | Course Schedule | Course Content