Introduction

I'm delighted to welcome you to our C++ Sets lesson! Remember, std::set in C++ is similar to sets in other programming languages. It is a container that stores unique elements, following a specific order. They're especially useful when you need to ensure that elements in a collection appear only once.

In this lesson, you'll consolidate your knowledge of creating and operating on sets using std::set. You will learn about immutable sets concepts through const correctness and discover how sets enhance performance. Ready, set, go!

Creating and Manipulating Sets

Let's begin by creating a set in C++. It can be done using the std::set from the C++ Standard Library.

C++ provides methods to manipulate sets, such as insert(), find(), erase(), and clear().

Both erase() methods can be used for removing elements from a set, but they behave slightly differently depending on their parameters:

  • erase(iterator): Erases an element by iterator.
  • erase(key): Erases elements by key. If the element is not found, it does nothing.

In addition to std::set, the C++ Standard Library also includes std::unordered_set, which is similar in functionality but differs in terms of element ordering. Unlike std::set, std::unordered_set does not maintain any specific order for its elements.

The methods discussed above for std::set such as insert(), find(), erase(), and clear() also apply to std::unordered_set. This makes std::unordered_set a convenient choice when order is not important and you want to prioritize faster average membership tests.

Set Operations

C++ provides built-in operations for std::set, such as union, intersection, and difference using functions and iterators from the <algorithm> header.

  • std::set_union(): Combines elements from both sets, excluding any duplicates. In this case, the result is a set containing {1, 2, 3, 4, 5, 6}.
  • std::set_intersection(): Returns a set with only the elements that are common to both sets. For these sets, the intersection is {3, 4}.
  • std::set_difference(): Returns a set containing elements that are in the first set but not in the second set. Here, the result is {1, 2} for set_1.difference(set_2).
  • std::inserter: A function that generates an iterator which inserts elements into the container at the specified position. It is used here to insert the resulting elements of std::set_union, std::set_intersection, and std::set_difference into the destination containers (union_set, intersection_set, difference_set) at their respective beginning positions.
Immutable Sets

While C++ does not have a built-in immutable set type, const std::set can be used to create an unmodifiable set; this practice is called const correctness. This is useful in scenarios where you need to guarantee the set's elements remain unchanged after creation.

Using const with a set ensures that the set cannot be modified after it's created, similar to Python's frozenset.

Performance Benefits of Sets

One of the key advantages of sets is their faster performance in membership tests, which results from their underlying data structures. The two primary types of sets in C++ — std::set and std::unordered_set — employ different structures to achieve their performance characteristics.

std::set uses a balanced binary search tree, which maintains elements in a specific sorted order. In contrast, std::unordered_set relies on a hash table. Hash tables map keys to indices in an array using a hash function, which distributes keys uniformly across the array. However, unlike std::set, elements in std::unordered_set are not stored in any particular order.

Please note that the runtimes reported in the above code snippet may vary when running the code multiple times or on different environments; that is, you will most probably get different numbers when running the code. What matters is the relative speed of retrieval for one data structure with respect to the others. Let's briefly discuss these results from a theoretical point of view:

  • Set: Membership test with std::set is efficient due to the balanced tree structure, leading to logarithmic time complexity (O(log n)).
  • Unordered set: std::unordered_set uses a hash table, which allows average constant time complexity (O(1)) for membership tests.
  • Array (vector): Checking for membership in a std::vector requires a linear search, leading to linear time complexity (O(n)).
Lesson Summary

Congratulations! You've just explored creating and manipulating sets, performing set operations, using immutable sets with const correctness, and understanding the performance benefits of sets in C++.

Remember, practice is key to solidifying your understanding. Happy coding!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal