Set Container in C++: Usage and Operations
In C++, the set container is part of the Standard Template Library (STL). A set is a container that stores unique elements in a specific order, usually sorted according to a comparison function. This container is implemented using a balanced binary search tree (often Red-Black Tree), which ensures that insertions, deletions, and lookups occur in logarithmic time complexity. This makes set ideal for scenarios where you need to maintain a collection of unique items and also require the elements to be sorted.
In this guide, we will explore everything about the set container, including how to construct sets, perform common operations, and effectively utilize its capabilities in C++.
Table of Contents
- Introduction to Set in C++
- Different Ways to Construct a Set
-
Common Operations on Set
insert()erase()find()count()size()empty()clear()
- Working with Custom Data Types
- Iterators in Sets
- Summary and Best Practices
1. Introduction to Set in C++
A set in C++ is a container that stores unique elements, sorted in a specific order (typically ascending by default). It provides efficient access to elements, with logarithmic time complexity for common operations like insertion, deletion, and lookup.
Key Features:
-
Unique Elements: Each element in a
setis unique. Duplicates are automatically discarded. - Sorted Order: Elements are stored in sorted order (default is ascending order).
- Efficient Operations: Operations such as insertion, deletion, and search occur in O(log n) time due to the tree-based implementation.
When to Use:
- Use
setwhen you need to store unique elements and want them to be automatically sorted. - If you don't need the elements to be ordered, consider using
unordered_setfor potentially faster operations.
2. Different Ways to Construct a Set
You can create a set in several ways depending on your needs.
2.1 Default Constructor
The default constructor creates an empty set.
set<int> s;
This creates an empty set of integers, which can be populated later.
2.2 Constructor with Initializer List
You can initialize a set directly with a list of values.
set<int> s = {1, 2, 3, 4, 5};
This creates a set containing the values 1, 2, 3, 4, 5 sorted in ascending order.
2.3 Constructor with Another Set
You can create a set by copying elements from another set.
set<int> s1 = {1, 2, 3, 4, 5};
set<int> s2(s1); // Initializes s2 as a copy of s1
2.4 Constructor with Another Container
You can create a set by copying elements from another container such as a vector or list.
vector<int> v = {1, 2, 3, 4, 5};
set<int> s(v.begin(), v.end()); // Initializes a set using iterators from a vector
2.5 Assignment Operator
The assignment operator allows you to copy elements from one set to another.
set<int> s1 = {1, 2, 3};
set<int> s2;
s2 = s1; // Now s2 contains the same elements as s1
The assignment operator performs a deep copy, meaning that the elements of s1 are fully copied into s2.
3. Common Operations on Set
3.1 insert()
The insert() function adds an element to the set. If the element already exists, it will not be added again.
Syntax:
- Insert a single element:
s.insert(element);
- Insert multiple elements using an initializer list:
s.insert({element1, element2, ...});
- Insert elements from another container:
s.insert(container.begin(), container.end());
Example:
set<int> s;
// Insert a single element
s.insert(10); // Inserts 10
s.insert(20); // Inserts 20
s.insert(30); // Inserts 30
// Insert multiple elements
s.insert({40, 50, 60}); // Inserts 40, 50, and 60
// Insert elements from another container
vector<int> v = {70, 80, 90};
s.insert(v.begin(), v.end()); // Inserts 70, 80, 90
After these operations, the set s will contain: {10, 20, 30, 40, 50, 60, 70, 80, 90}.
3.2 erase()
The erase() function removes an element from the set.
Syntax:
- Erase a single element:
s.erase(element);
- Erase an element using an iterator:
s.erase(iterator);
- Erase a range of elements:
s.erase(start_iterator, end_iterator);
Example:
set<int> s = {10, 20, 30, 40, 50};
// Erase a single element
s.erase(20); // Removes 20
// Erase using an iterator
auto it = s.find(30);
s.erase(it); // Removes 30
// Erase a range of elements
s.insert({10, 20, 30, 40, 50}); // Reinsert elements for demonstration
auto start = s.find(10);
auto end = s.find(40);
s.erase(start, end); // Removes 10, 20, and 30
After these operations, the set s will contain: {40, 50}.
3.3 find()
The find() function searches for an element in the set and returns an iterator to it if found, or end() if not found.
Syntax:
auto it = s.find(element);
Example:
set<int> s = {10, 20, 30};
auto it = s.find(20);
if (it != s.end()) {
cout << "Element found: " << *it << endl; // Outputs: Element found: 20
} else {
cout << "Element not found." << endl;
}
3.4 count()
The count() function returns the number of occurrences of an element in the set. Since set only allows unique elements, it will return either 0 or 1.
Syntax:
size_t count = s.count(element);
Example:
set<int> s = {10, 20, 30};
cout << "Count of 20: " << s.count(20) << endl; // Outputs: Count of 20: 1
cout << "Count of 40: " << s.count(40) << endl; // Outputs: Count of 40: 0
3.5 size()
The size() function returns the number of elements in the set.
Syntax:
size_t size = s.size();
Example:
set<int> s = {10, 20, 30};
cout << "Size of set: " << s.size() << endl; // Outputs: Size of set: 3
3.6 empty()
The empty() function checks whether the set is empty.
Syntax:
bool isEmpty = s.empty();
Example:
set<int> s;
cout << "Is set empty? " << (s.empty() ? "Yes" : "No") << endl; // Outputs: Yes
s.insert(10);
cout << "Is set empty? " << (s.empty() ? "Yes" : "No") << endl; // Outputs: No
3.7 clear()
The clear() function removes all elements from the set.
Syntax:
s.clear();
Example:
set<int> s = {10, 20, 30};
s.clear(); // Removes all elements
After calling clear(), the set will be empty.
4. Working with Custom Data Types
You can store custom data types in a set, provided that the type supports comparison using the < operator or a custom comparator.
Example:
#include <iostream>
#include <set>
using namespace std;
struct Person {
string name;
int age;
bool operator<(const Person& other) const {
return name < other.name; // Define sorting order by name
}
};
int main() {
set<Person> people;
people.insert({"Alice", 30});
people.insert({"Bob", 25});
people.insert({"Charlie", 35});
for (const auto& person : people) {
cout << person.name << " - " << person.age << endl;
}
return 0;
}
In this example, the Person struct is stored in a set, and the sorting order is based on the name field.
5. Iterators in Sets
You can iterate over the elements of a set using iterators, just like other STL containers.
Syntax:
for (auto it = s.begin(); it != s.end(); ++it) {
// Access the element via *it
}
You can also use range-based for loops:
for (const auto& element : s) {
// Access each element
}
6. Summary and Best Practices
Key Takeaways:
-
setis ideal for storing unique elements that need to be sorted. - Common operations like
insert(),erase(), andfind()are efficient due to the tree-based implementation. - Use
setwhen you need elements to be stored in a specific order. - To store custom types, ensure they support the
<operator or provide a custom comparator.
Best Practices:
- Ensure your custom types can be compared using the
<operator or provide a custom comparator. - Use
setwhen the order of elements is important and uniqueness is required. - If performance is critical and order doesn't matter, consider using
unordered_set.
This concludes our guide on using set in C++. It's an essential tool for many common programming tasks where sorting and uniqueness are required.
Top comments (0)