std::unordered_multimap is an unordered associative container in C++ STL that stores elements as key-value pairs using a hash table. Unlike std::unordered_map, it allows multiple elements to have the same key while providing efficient average-case insertion, deletion, and search operations.
- Stores multiple values associated with the same key and does not maintain elements in any specific order.
- Provides average-case O(1) complexity for insertion, deletion, and lookup operations using hashing
#include <bits/stdc++.h>
using namespace std;
int main() {
// Creating an empty unordered_multimap
unordered_multimap<int, string> umm1;
// Creating unordered_multimap using
// initializer list
unordered_multimap<int, string> umm2 =
{{1, "Geeks"}, {2, "For"}, {1, "C++"}};
for (auto x : umm2)
cout << x.first << ": " << x.second
<< endl;
return 0;
}
Output
2: For 1: C++ 1: Geeks
Explanation:
- umm1 creates an empty unordered multimap.
- umm2 initializes the container using an initializer list and allows duplicate keys.
Syntax
std::unordered_multimap is defined in the <unordered_map> header file.
#include <unordered_map>
unordered_multimap<key_type, value_type> umm;
Where:
- key_type represents the type of keys.
- value_type represents the type of mapped values.
- umm is the name of the unordered multimap.
Basic Operations
The basic operations on unordered multimap are shown below:
Inserting Elements
New key-value pairs can be inserted using the insert() function. This function allows inserting multiple elements with the same key. This map container does not support the use of [] operator because multiple elements with the same key can be present.
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multimap<int, string> umm;
// Insert elements using insert()
umm.insert({2, "For"});
umm.insert({3, "C++"});
umm.insert({2, "Geeks"});
for (auto x : umm)
cout << x.first << ": "
<< x.second << endl;
return 0;
}
Output
3: C++ 2: Geeks 2: For
Accessing Elements
Elements can be accessed by its position by moving begin() and end() iterators, but it is not useful. In unordered multimap, accessing value by their key is the primary operation. This can be done by using find() method.
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multimap<int, string> umm =
{{2, "For"}, {3, "C++"}, {2, "Geeks"}};
// Find 2nd element
auto it = next(umm.begin(), 1);
if (it != umm.end())
cout << it->first << ": " <<
it->second;
else
cout << "Element not found!";
return 0;
}
Output
2: For
Finding Elements
In unordered multimap, elements can be accessed by their key using find() method. This method searches for the given key and returns the iterator to the first element with the given key. This iterator can be dereferenced to access the key(first) and value(second) of the pair.
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multimap<int, string> umm =
{{2, "For"}, {3, "C++"}, {2, "Geeks"}};
// Searching for key '2' using find()
auto it = umm.find(2);
if (it != umm.end())
cout << it->first << ": " <<
it->second;
else
cout << "Element not Found!";
return 0;
}
Output
2: Geeks
Updating Elements
Unordered multimap allows users to update the associated value of any key. This can be done by accessing the element and assigning the new value (second member).
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multimap<int, string> umm =
{{2, "For"}, {3, "C++"}, {2, "Geeks"}};
// Searching for key '2' using find()
auto it = umm.find(2);
// Updating value
it->second = "Java";
for (auto x: umm)
cout << x.first << ": " << x.second
<< endl;
return 0;
}
Output
2: Java 2: For 3: C++
Traversing
Traversing through an unordered multimap can be done using begin() or end() iterators or a range-based for loop.
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multimap<int, string> umm =
{{1, "Geeks"},{2, "For"},{1, "C++"}};
// Traversing using iterators with loop
for(auto it = umm.begin(); it != umm.end(); it++)
cout << it->first << ": " << it->second
<< endl;
return 0;
}
Output
1: C++ 1: Geeks 2: For
Explanation: In the above program, traversal through the unordered multimap is done using an iterator with a loop. Starting from beginning, in each iteration, the iterator it points to a pair and then incremented. The traversal stops when it encounters the end() iterator.
Deleting Elements
Elements can be deleted using erase() by passing either the key or the iterator. If the key is passed, then all the elements with the same key are deleted.
#include <bits/stdc++.h>
using namespace std;
int main() {
unordered_multimap<int, string> umm =
{{1, "Geeks"}, {2, "For"},{3, "C++"},
{1, "STL"}};
// Delete all elements which are
// associated with key 1
umm.erase(1);
// Delete first element
// using iterator
umm.erase(umm.begin());
for(auto x: umm)
cout << x.first << " " << x.second;
return 0;
}
Output
2 For
Time Complexity
The below table lists the time complexity of the above operations on unordered multimap:
| Operation | Average Complexity |
|---|---|
| Insertion | O(1) |
| Deletion | O(1) |
| Search | O(1) |
| Traversal | O(n) |
| Access by position | O(n) |
Internal Working
std::unordered_multimap internally uses a hash table to store key-value pairs.
- Keys are hashed to determine their bucket location.
- Multiple elements with the same key can exist in the same bucket.
- Hash collisions are handled by storing multiple elements in a bucket.
- Insert, delete, and search operations take O(1) average time.
- In the worst case, the time complexity can become O(n).
Unordered Multimap vs Unordered Map
| Feature | unordered_multimap | unordered_map |
|---|---|---|
| Duplicate Keys | Allowed | Not Allowed |
| Element Storage | Multiple values per key | One value per key |
| Ordering | Unordered | Unordered |
| Average Search Complexity | O(1) | O(1) |
Common Member Functions
Following is the list of all member functions of std::unordered_multimap class in C++:
Functions | Description |
|---|---|
Returns an iterator pointing to the first element | |
Returns an iterator pointing to the position beyond the last element | |
| clear() | Delete all elements of the unordered multimap. |
| size() | Returns the number of elements |
Swaps two containers | |
| bucket_count() | Returns the number of buckets |
Counts elements with a key | |
Searches for a key | |
Checks whether the container is empty | |
Removes elements | |
Removes all elements | |
Inserts a key-value pair | |
Constructs and inserts an element | |
This function is used to swap two unordered multimaps. |