Unordered Multiset in C++ STL
Last Updated :
03 Mar, 2025
In C++, unordered multiset is an unordered associative container that works similarly to an unordered set, but it can store multiple copies of the same value. It provides fast insert, delete and search operations using hashing, but the elements are not in any particular order.
Example:
C++
#include <iostream>
#include <unordered_set>
using namespace std;
int main() {
// Creating unordered multiset of
// integers
unordered_multiset<int> ums =
{5, 1, 3, 4, 1};
for (auto x : ums)
cout << x << " ";
return 0;
}
Explanation: In the above program, we create an unordered multiset ums with values: 5, 1, 3, 4 and 1. We can see from the output that there is no order of the elements and we were able to store 1 two times.
Syntax
Unordered multiset is defined as the std::unordered_multiset class template inside the <unordered_multiset> header file.
unordered_multiset<T> ums;
where,
- T: Type of elements in the unordered multiset.
- ums: Name assigned to the unordered multiset.
Declaration and Initialization
We can declare and initialize an unordered multiset in different ways as shown in the below example:
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
// Create an empty unordered multiset
unordered_multiset<int> ums1;
// Create and initialize elements
// using initialzer list
unordered_multiset<int> ums2 =
{5, 3, 4, 1, 1};
for(auto x : ums2)
cout << x << " ";;
return 0;
}
Explanation: In this example, we initialize an unordered multiset in three ways:
- Statement unordered_multiset<int> ums1 creates an empty unordered multiset.
- Statement unordered_multiset<int> ums2 = {2, 5, 3, 4, 1, 1} initialize the unordered multiset using initializer list.
Basic Operations
The basic operations of unordered multiset are shown below:
1. Inserting Elements
Elements can be inserted into an unordered multiset using the insert() method. The position of the element is determined by the hashing function so we cannot specify any position while inserting.
Example:
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multiset<int> ums;
// Insert elements using insert()
ums.insert(5);
ums.insert(1);
ums.insert(3);
ums.insert(1);
ums.insert(2);
ums.insert(4);
for (auto x : ums) cout << x << ' ';
return 0;
}
2. Accessing Elements
An unordered multiset does not allow direct access to elements by index as accessing elements is not the primary operation of this container. However, we have to increment or decrement iterator obtained from begin() or end() methods respectively to access the element by position. This can also be done with the help of next() or advance() function.
Example:
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multiset<int> ums =
{5, 1, 3, 2, 4, 1};
// Accessing element using iterator
auto it = next(ums.begin(), 2);
cout << *it;
return 0;
}
Explanation: In the above program, iterator it accesses the third element by advancing begin() by 2 positions using next().
3. Updating Elements
Unordered multiset does allow changing the value of the accessed elements as it may disrupt the container functions.
4. Finding Elements
It is the primary operation for which this container is optimized for. The find() method provides fast search of any element by value. This function returns iterator to the element if found, otherwise returns iterator to the end().
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multiset<int> ums =
{5, 1, 3, 4, 1};
// Finding 3
auto it = ums.find(3);
if (it != ums.end()) cout << *it;
else cout << "Element not Found!";
return 0;
}
5. Traversing
We can traverse unordered multiset either using range-based for loop or using begin() and end() iterator.
Example:
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multiset<int> ums =
{5, 1, 3, 4, 1};
// Using range-based for loop
for(auto x : ums)
cout << x << " ";
cout << "\n";
return 0;
}
6. Deleting Elements
We can use erase() method to delete elements from unordered multiset. It deletes all occurrences of an elements if we provide the value of the element. If we provide iterator of the element, it deletes only that value from the unordered multiset.
Example:
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multiset<int> ums =
{5, 1, 3, 2, 4, 1};
// Delete all occurrences of element 1
ums.erase(1);
// Delete 2 using iterator
ums.erase(ums.find(2));
for (auto x: ums) cout << x << " ";
return 0;
}
Explanation: In the above program,
- ums.erase(1) deletes all occurrences of the element 1 from the set.
- ums.erase(ums.find(2)) deletes one occurrence of the element 2 by using an iterator returned from find(2).
Time Complexity
The below table lists the time complexity of the above operations on unordered multiset:
Operation | Time Complexity |
---|
Inserting elements | O(1) average |
Deleting elements | O(1) average |
Finding elements by value | O(1) average |
Accessing elements by position | O(n) |
Traverse the multiset | O(n) |
Other Common Operations
Unordered multiset is used in many situations for different purposes. The following examples’ aim is to help you master unordered multiset beyond the basics:
Internal Working
In C++, unordered multiset container provides the built-in implementation of a hash table data structure. Each element is hashed to a bucket and elements with the same hash value are stored in the same bucket. These buckets are generally implemented as linked lists. This allows for fast access and insertion, basically with constant time complexity (O(1)) for operations like insert(), erase(), and find(). However, due to hash collisions, the time complexity can degrade to O(n) in the worst case.
Unordered Multiset vs Multiset
Primary difference between unordered multiset and multiset is shown below:
- Unordered multiset allows multiple occurrences of the same element and does not maintain the order of the elements. Elements are stored based on their hash values.
- Multiset allows multiple occurrences of the same element and also elements store in sorted way either ascending or descending.
All Member Functions
Following is the list of all member functions of std::unordered_multiset class in C++:
Function | Description |
---|
insert() | Inserts new elements in the unordered multiset. |
begin() | Returns an iterator pointing to the first element in the container or the first element in one of its buckets. |
end() | Returns an iterator pointing to the position immediately after the last element in the container or to the position immediately after the last element in one of its buckets. |
empty() | It returns true if the unordered multiset container is empty. Otherwise, it returns false. |
find() | Returns an iterator that points to the position which has the element. |
cbegin() | Returns a constant iterator pointing to the first element in the container or the first element in one of its buckets. |
cend() | Returns a constant iterator pointing to the position immediately after the last element in the container or immediately after the last element in one of its buckets. |
equal_range() | Returns the range in which all the elements are equal to a given value. |
emplace() | Inserts a new element in the unordered multiset container. |
clear() | Clears the contents of the unordered multiset container. |
count() | Returns the count of elements in the unordered multiset container which is equal to a given value. |
size() | The size() method of unordered multiset is used to count the number of elements of unordered set it is called with. |
max_size | The max_size() of unordered multiset takes the maximum number of elements that the unordered multiset container is able to hold. |
swap() | Swaps the contents of two unordered multiset containers. |
erase() | Used to remove either a single element or, all elements with a definite value or, a range of elements ranging from the start(inclusive) to the end(exclusive). |
bucket() | Returns the bucket number in which a given element is. Bucket size varies from 0 to bucket_count-1. |
bucket_size() | Returns the number of elements in the bucket that has the element val. |
reserve() | The reverse() function of unordered multiset sets the number of buckets in the container (bucket count) to the most appropriate to contain at least n elements. |
max_bucket_count() | Returns the maximum number of buckets that the unordered multiset container can have. |
load_factor() | Returns the current load factor in the unordered multiset container. |
max_load_factor() | Returns the maximum load factor of the unordered multiset container. |
bucket_count() | Returns the total number of buckets in the unordered multiset container. |
hash_function() | This hash function is a unary function that takes a single argument only and returns a unique value of type size_t based on it. |
rehash() | Sets the number of buckets in the container to N or more. |
key_eq() | Returns a boolean value according to the comparison. |
emplace_hint() | Inserts a new element in the unordered multiset container. |
get_allocator | This function gets the stored allocator object and returns the allocator object used to construct the container. |