Multimap

Overview

The map container described previously had the restriction that all of the keys had to be unique. Associating a value with a key overwrote the value previously associated with that key. The multimap container, however, has no such restriction. As many values as you choose can be associated with a particular key. This flexibility comes at the price of making multimap more difficult to use, as will be discussed below. A good understanding of the map container is required to understand this document.

 

Declaring a Multimap

To use multimap, you must #include <map>. Like all of the C++ Standard Library, multimap is declared with the std namespace. You can declare an instance of a multimap with a declaration similar to the following:

using namespace std;
multimap<string, int> mMap;

The above declaration would specify a map that associates strings with integers. The multimap container provides bidirectional iterators. The following declaration demonstrates how to declare an iterator for multimap:

multimap<string, int>::iterator itr;

Creating Key/Value Associations

You can add a key/value association to a multimap by calling the multimap::insert() method. insert() accepts a pair object that specifies the key/value association you want to add. The "first" member of the pair object is the key, and the "second" member of the pair specifies the value to associate with the key. For example, the following code would add an association of the value 3 with the string "Bob."

mMap.insert(make_pair(string("Bob"), int(3)));

More info on the pair class template and make_pair() can be found in the documentation for map.

 

How to Access the Value(s) Associated With a Key

The multimap::find() method returns an iterator to the first pair object that is associated with a given key. To access the entire sequence of values associated with a key, you can call multimap::upper_bound() to get an iterator that is one past the last pair object that is associated with the given key. This will give you starting and ending iterators, which you can then use to traverse the sequence of values associated with the key. I know that's a mouthful. Take a deep breath and read it again. :) Here is a clarifying example:

void PrintAllValuesAssociatedWithKey(multimap<string, int> &mMap, string &key)
{
	multimap<string, int>::iterator itr;
	multimap<string, int>::iterator lastElement;
	
	// locate an iterator to the first pair object associated with key
	itr = mMap.find(key);
	if (itr == mMap.end())
		return; // no elements associated with key, so return immediately

	cout << "The following values are associated with the key " << key << endl;
	
	// get an iterator to the element that is one past the last element associated with key
	lastElement = mMap.upper_bound(key);

	// for each element in the sequence [itr, lastElement)
	for ( ; itr != lastElement; ++itr)
		cout << itr->second << endl;

}

 

Element Requirements

The multimap container's element requirements for both the key and value types are exactly the same as for map. Look at the map document for more information.

 

Methods

Multimap defines the following methods:

Operation

Description

Time Complexity

swap

Swaps elements with another multimap. This operation is performed in constant time.

Ex: multimap1.swap(multimap2);

O(1)

count

Returns the number of values associated with a particular key.

Ex: cout << multimap1.count("Bob"); // display the number of values associated with "Bob"

O(log n + m)

m=number of values associated with the key

upper_bound

Returns an iterator to the pair object that is one element beyond the last element associated with key. Returns multimap::end() if no such element exists. This function is useful for determining the starting and ending iterators for the sequence of values that are associated with a given key.

Ex: if (itr == multimap1.upper_bound("Bob"))

cout << "No more values associated with Bob. \n";

O(log n)

lower_bound

Returns an iterator to the first pair object whose key is greater than or equal to the given key. Returns multimap::end() if no such element exists.

Ex: itr = multimap1.lower_bound("Bob");

O(log n)

begin

Returns an iterator to the first pair in the multimap.

Ex: itr = multimap1.begin();

O(1)

end

Returns an iterator that is just beyond the end of the multimap.

O(1)

size

Returns the number of elements contained by the multimap. You should use empty() to test whether or not size equals 0, because empty() may be much faster.

cout << multimap1.size();

O(n) or better.

empty

Returns true if the multimap contains zero elements.

O(1)

find

Accepts a key and returns an iterator to the first pair element that matches the key. If the key is not found in the multimap, this method returns end().

if ( (itr = multimap1.find("Bob")) == multimap1.end())

cerr << "Bob was not found in the multimap." << endl;

else

cout << "Bob was found in the multimap." << endl;

O(log n)

insert

Adds the key/value association specified by a pair object to the multimap. The first member of the pair is the key, and the second value is the value associated with key.

Ex: multimap1.insert(make_pair(string("Bob"), int(5)));

O(log n)

erase

There are three overloaded forms of this method.

The first accepts a single iterator, and removes the element implied by the iterator from the multimap. The multimap should be non-empty. O(1).

Ex: assert(!multimap1.empty());

multimap1.erase(multimap1.begin()); // remove the first element

The second accepts two iterators, that specify a range of values within the multimap to be removed. The time complexity is logarithmic plus linear time for the length of the sequence being removed. The two iterators must be valid iterators within the sequence contained by the multimap. Formally, the range of values [starting, ending) are removed. At worst, this is an O(n) operation.

Ex: multimap1.erase(multimap1.begin(), multimap1.end()); // erase the entire multimap

The last accepts an object of the key type, and removes all occurrences of the key from multimap. O(log n + m). m=The number of values associated with the given key.

Ex: multimap1.erase(string("Bob")); // removes all occurences of "Bob"

See description

 

Notes on Interpreting the Above Table

For the example code in the above table, <map>, <iostream>, and <string> are assumed to be #include'd, and the line "using namespace std;" is assumed to appear at the top of the source file. Also, the following declarations are assumed:

multimap<string, int> multimap1;

multimap<string, int> multimap2;

mutlimap<string, int>::iterator itr;

 

Author: Rodney Myers 4/23/00