std::multiset
std::multiset
is a container in the C++ Standard Template Library (STL) that stores elements in a sorted order, allowing multiple elements with the same value. Like std::set
, it is typically implemented as a balanced binary search tree (usually a red-black tree), providing logarithmic time complexity for insertion, deletion, and search operations.
#include <iostream>
#include <set>
#include <string>
int main() {
std::multiset<int> numbers = {5, 2, 8, 2, 1, 9, 3, 7, 3};
// Inserting elements
numbers.insert(4);
numbers.insert(2); // Duplicate allowed
// Printing the multiset
std::cout << "Numbers in the multiset:" << std::endl;
for (const auto& num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// Counting occurrences
std::cout << "Count of 2: " << numbers.count(2) << std::endl;
// Finding elements
auto range = numbers.equal_range(3);
std::cout << "Elements equal to 3: ";
for (auto it = range.first; it != range.second; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// Removing an element
numbers.erase(numbers.find(3)); // Removes only one instance of 3
// Size of the multiset
std::cout << "Number of elements: " << numbers.size() << std::endl;
return 0;
}
multiset
of integers is created and initializedinsert()
is used to add new elements, including duplicatescount()
returns the number of occurrences of an elementequal_range()
finds a range of elements equal to a given valueerase()
with an iterator removes a single instance of an elementsize()
returns the total number of elements, including duplicates#include <iostream>
#include <set>
#include <string>
struct Person {
std::string name;
int age;
// This is used for printing
friend std::ostream& operator<<(std::ostream& os, const Person& p) {
return os << p.name << " (" << p.age << ")";
}
};
// Custom comparator for descending order of age
struct PersonComparator {
bool operator()(const Person& a, const Person& b) const {
if (a.age != b.age) {
return a.age > b.age; // Descending order of age
}
return a.name < b.name; // Ascending order of name if ages are equal
}
};
int main() {
std::multiset<Person, PersonComparator> people;
people.insert({"Alice", 30});
people.insert({"Bob", 25});
people.insert({"Charlie", 35});
people.insert({"David", 30});
people.insert({"Eve", 25});
for (const auto& person : people) {
std::cout << person << std::endl;
}
return 0;
}
Person
struct is definedPersonComparator
is created for descending age ordermultiset
is initialized with Person
objects and the custom comparatorstd::multiset
#include <iostream>
#include <set>
#include <string>
#include <map>
int main() {
std::multiset<std::string> words = {
"apple", "banana", "cherry", "date", "apple", "fig",
"grape", "apple", "banana", "elderberry"
};
// Count frequency of each word
std::map<std::string, int> frequency;
for (const auto& word : words) {
frequency[word]++;
}
// Print frequency
std::cout << "Word frequencies:" << std::endl;
for (const auto& pair : frequency) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
// Remove all instances of a specific word
std::string word_to_remove = "apple";
auto removed = words.erase(word_to_remove);
std::cout << "\nRemoved " << removed << " instance(s) of '" << word_to_remove << "'" << std::endl;
// Print remaining words
std::cout << "\nRemaining words:" << std::endl;
for (const auto& word : words) {
std::cout << word << " ";
}
std::cout << std::endl;
return 0;
}
multiset
of strings is created with duplicate wordsmap
is used to count the frequency of each worderase()
function is used to remove all instances of a specific word#include <iostream>
#include <set>
#include <algorithm>
void printRange(const std::multiset<int>& ms, int lower, int upper) {
auto start = ms.lower_bound(lower);
auto end = ms.upper_bound(upper);
std::cout << "Elements in range [" << lower << ", " << upper << "]: ";
std::for_each(start, end, [](int n) { std::cout << n << " "; });
std::cout << std::endl;
}
int main() {
std::multiset<int> numbers = {1, 2, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 10};
std::cout << "All numbers: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
// Demonstrate lower_bound and upper_bound
printRange(numbers, 3, 7);
// Count elements in a range
int rangeStart = 4, rangeEnd = 8;
auto startIt = numbers.lower_bound(rangeStart);
auto endIt = numbers.upper_bound(rangeEnd);
int count = std::distance(startIt, endIt);
std::cout << "Number of elements between " << rangeStart
<< " and " << rangeEnd << ": " << count << std::endl;
// Remove a range of elements
numbers.erase(numbers.lower_bound(5), numbers.upper_bound(8));
std::cout << "After removing range [5, 8]: ";
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
multiset
lower_bound()
returns an iterator to the first element not less than a given valueupper_bound()
returns an iterator to the first element greater than a given valueprintRange
function shows elements within a specific rangestd::distance
is used to count elements within a rangeerase()
with a range of iterators removes all elements within that rangePerformance: While multiset
provides good performance for most operations, consider using std::vector
or std::deque
for small datasets or when frequent insertions/deletions are not required.
Memory Usage: multiset
typically uses more memory than a simple array due to its tree structure.
Iteration Order: Elements are always traversed in the sorted order defined by the comparison function.
No Direct Element Modification: Elements in a multiset
cannot be modified directly through iterators to maintain the correct ordering.
std::multiset
is a powerful container in C++ for storing sorted elements while allowing duplicates. Key points to remember:
lower_bound
and upper_bound
std::multiset
is particularly useful in situations where you need to maintain a sorted collection of elements, including duplicates. It's commonly used in scenarios such as:
- Implementing algorithms that require sorted data with repetitions
- Frequency analysis of elements
- Maintaining ordered lists where duplicates are meaningful
- Scenarios where both sorting and the ability to store multiple identical elements are crucial
Understanding when to use std::multiset
over other containers like std::set
or std::vector
is key to writing efficient and clear C++ code in various application domains.