Allows Duplicates:
We have discussed unordered_map in our previous post, but there is a limitation, we can not store duplicates in unordered_map, that is if we have a key-value pair already in our unordered_multimap and another pair is inserted, then both will be there whereas in case of unordered_map the previous value corresponding to the key is updated by the new value that is only would be there. Even can exist in unordered_multimap twice.
Internal Representation:
The internal implementation of unordered_multimap is the same as that of unordered_map but for duplicate keys, another count value is maintained with each key-value pair. As pairs are stored in the hash table, there is no particular order among them but pairs with the same keys come together in the data structure whereas pairs with the same values are not guaranteed to come together.
Time Complexity:
All operation on unordered_multimap takes a constant amount of time on average but time can go to linear in the worst case depending on internally used hash function but in long run unordered_multimap outperforms multimap (tree-based multimap).
Functions:
unordered_multimap supports many functions which are demonstrated in the below code :
CPP
#include <bits/stdc++.h>
using namespace std;
typedef unordered_multimap<string, int >::iterator unit;
void printUmm(unordered_multimap<string, int > umm)
{
unit it = umm.begin();
for (; it != umm.end(); it++){
cout << "<" << it->first << ", " << it->second
<< "> " ;
cout << endl;
}
}
int main()
{
unordered_multimap<string, int > umm1;
unordered_multimap<string, int > umm2(
{ { "apple" , 1 },
{ "ball" , 2 },
{ "apple" , 10 },
{ "cat" , 7 },
{ "dog" , 9 },
{ "cat" , 6 },
{ "apple" , 1 } });
umm1 = umm2;
printUmm(umm1);
if (umm2.empty())
cout << "unordered multimap 2 is empty\n" ;
else
cout << "unordered multimap 2 is not empty\n" ;
cout << "Size of unordered multimap 1 is "
<< umm1.size() << endl;
string key = "apple" ;
unit it = umm1.find(key);
if (it != umm1.end()) {
cout << "\nkey " << key << " is there in unordered "
<< " multimap 1\n" ;
cout << "\none of the value associated with " << key
<< " is " << it->second << endl;
}
else
cout << "\nkey " << key
<< " is not there in unordered"
<< " multimap 1\n" ;
int cnt = umm1.count(key);
cout << "\ntotal values associated with " << key
<< " are " << cnt << "\n\n" ;
printUmm(umm2);
umm2.insert(make_pair( "dog" , 11));
umm2.insert({ { "alpha" , 12 }, { "beta" , 33 } });
cout << "\nAfter insertion of <alpha, 12> and <beta, "
"33>\n" ;
printUmm(umm2);
umm2.erase( "apple" );
cout << "\nAfter deletion of apple\n" ;
printUmm(umm2);
umm1.clear();
umm2.clear();
if (umm2.empty())
cout << "\nunordered multimap 2 is empty\n" ;
else
cout << "\nunordered multimap 2 is not empty\n" ;
}
|
Output
<dog, 9>
<cat, 6>
<cat, 7>
<ball, 2>
<apple, 1>
<apple, 10>
<apple, 1>
unordered multimap 2 is not empty
Size of unordered multimap 1 is 7
key apple is there in unordered multimap 1
one of the value associated with apple is 1
total values associated with apple are 3
<dog, 9>
<cat, 6>
<cat, 7>
<ball, 2>
<apple, 1>
<apple, 10>
<apple, 1>
After insertion of <alpha, 12> and <beta, 33>
<alpha, 12>
<dog, 11>
<dog, 9>
<beta, 33>
<cat, 6>
<cat, 7>
<ball, 2>
<apple, 1>
<apple, 10>
<apple, 1>
After deletion of apple
<alpha, 12>
<dog, 11>
<dog, 9>
<beta, 33>
<cat, 6>
<cat, 7>
<ball, 2>
unordered multimap 2 is empty
As we can see in the above code most of the operations work similar to unordered_map but some things to note are :
We can use the initializer list for initializing and inserting many pairs at once.
There is no [] operator for unordered_multimap because values corresponding to a key are not unique, there can be many values associated with a single key so [] operator can not be applied to them.
Erase function deletes all instances of values associated with the supplied key.
Find function returns an iterator to any instance of key-value pair among all pairs associated with that key.
How to access/delete a specific value for a key?
If we want to check whether a specific value is there or not, we need to loop over all pairs of key-value until we get our specific value, if we get our specific value in the unordered_multimap then use erase(position) method to delete that specific value from unordered_multimap.
CPP
#include <bits/stdc++.h>
using namespace std;
void printUmm(unordered_multimap<string, int >& umm)
{
auto it1 = umm.begin();
for (; it1 != umm.end(); it1++) {
cout << "<" << it1->first << ", " << it1->second
<< "> " ;
cout << endl;
}
}
int main()
{
unordered_multimap<string, int > umm{
{ "apple" , 1 }, { "ball" , 2 }, { "apple" , 10 },
{ "cat" , 7 }, { "dog" , 9 }, { "cat" , 6 },
{ "apple" , 1 }
};
auto it = umm.begin();
while (it != umm.end()) {
if (it->second == 1)
break ;
it++;
}
if (it != umm.end())
umm.erase(it);
cout << "After deletion of value 1 from umm" << endl;
printUmm(umm);
return 0;
}
|
Output
After deletion of value 1 from umm
<dog, 9>
<cat, 6>
<cat, 7>
<ball, 2>
<apple, 10>
<apple, 1>
Methods of unordered_multimap:
- begin()– Returns an iterator pointing to the first element in the container or to the first element in one of its bucket.
- end()– Returns an iterator pointing to the position after the last element in the container or to the position after the last element in one of its bucket.
- count()– Returns the number of elements in the container whose key is equal to the key passed in the parameter.
- cbegin()– Returns a constant iterator pointing to the first element in the container or to the first element in one of its bucket.
- cend()– Returns a constant iterator pointing to the position after the last element in the container or to the position after the last element in one of its bucket.
- clear() – Clears the contents of the unordered_multimap container.
- size()– Returns the size of the unordered_multimap. It denotes the number of elements in that container.
- swap()– Swaps the contents of two unordered_multimap containers. The sizes can differ of both the containers.
- find()– Returns an iterator which points to one of the elements which have the key k.
- bucket_size()– Returns the number of elements in the bucket n.
- empty()– It returns true if the unordered_multimap container is empty. Otherwise, it returns false.
- equal_range()– Returns the range in which all the element’s key is equal to a key.
- operator=– Copy/Assign/Move elements from different container.
- max_size()– Returns the maximum number of elements that the unordered_multimap container can hold.
- load_factor()– Returns the current load factor in the unordered_multimap container.
- key_eq()– Returns a boolean value according to the comparison.
- emplace()– Inserts a new {key, element} in the unordered_multimap container.
- emplace_hint()– Inserts a new {key:element} in the unordered_multimap container.
- bucket_count()– Returns the total number of buckets in the unordered_multimap container.
- bucket()– Returns the bucket number in which a given key is.
- max_load_factor()– Returns the maximum load factor of the unordered_multimap container.
- rehash()– Sets the number of buckets in the container to N or more.
- reserve()– Sets the number of buckets in the container (bucket_count) to the most appropriate number so that it contains at least n elements.
- 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.
- max_bucket_count()– Returns the maximum number of buckets that the unordered multimap container can have.
Recent articles on unordered_multimap
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
Whether you're preparing for your first job interview or aiming to upskill in this ever-evolving tech landscape,
GeeksforGeeks Courses are your key to success. We provide top-quality content at affordable prices, all geared towards accelerating your growth in a time-bound manner. Join the millions we've already empowered, and we're here to do the same for you. Don't miss out -
check it out now!
Last Updated :
28 Jul, 2022
Like Article
Save Article