Table of Contents
Maps in C++ store the data in form of key and value pairs. Each value is identified by a key and no two keys are the same.
Maps are widely used in problems that involve searching large data such as a database, cache applications, data compression, etc.
This article discusses the two different types of maps in C++ and the methods to print map in C++.
Map vs Unordered Map
There are two different types of maps found in C++. These types are different in the implementation as well as in the performance.
- The map is defined in the “map” header file and stores the key-value pairs in the sorted order by keys (increasing by default).
- It is internally implemented using the self-balancing binary search tree such as the red-black tree.
- On the other hand, the unordered map is found in the “unordered_map” header file.
- It has no specific ordering and is implemented using the hash table.
- The time complexity of insertion, deletion, and searching operation in O(log n) in the case of the map.
- While the unordered map has the O(1) average-case time complexity of these operations.
Print Map in C++ Using Iterator
An iterator is similar to a pointer that points to a specific memory location of the associated container.
You can traverse and print a map as well as an unordered map using iterators in a loop. You can define an iterator as given below.
Iterator for map:
1 2 3 |
map<type, type>::iterator name; |
Iterator for unordered map:
1 2 3 |
unordered_map<type, type>::iterator name; |
Let us see the code to print a map.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#include <iostream> #include <map> using namespace std; int main() { map<int, string> myMap; myMap.insert(make_pair(1, "Name")); myMap.insert(make_pair(2, "Age")); myMap.insert(make_pair(4, "Section")); myMap.insert(make_pair(3, "Class")); map<int, string>::iterator itr; for(itr=myMap.begin();itr!=myMap.end();itr++) { cout<<itr->first<<" "<<itr->second<<endl; } return 0; } |
Notice the use of make_pair()
function. It takes two values and creates a key-value pair for inserting them into the map.
Also notice the begin()
and end()
function. They return the starting and ending iterator respectively.
Output:
2 Age
3 Class
4 Section
Notice that the output is sorted by keys even though the code inserted the data in a different order.
Note that you can use the auto
keyword to define the iterator starting from C++11.
To make the compiler automatically detect the type of the variable you can use the auto
keyword. Hence you do not require the lengthy declaration.
You will see the use of the auto
keyword in the following section.
Print Map in C++ Using Range-Based for Loop
The range-based for loop makes it easier to traverse a container like a map. It automatically traverses all the items sequentially, therefore, eliminating all the clutter.
You can traverse the map and unordered map in a range-based loop by using the auto
variable as well as the custom iterator.
Let us see the code that prints the content of an unordered map using the auto
variable and a range-based for loop.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <iostream> #include <unordered_map> using namespace std; int main() { unordered_map<int, string> myMap; myMap.insert(make_pair(1, "Name")); myMap.insert(make_pair(2, "Age")); myMap.insert(make_pair(4, "Section")); myMap.insert(make_pair(3, "Class")); for(auto &itr: myMap) { cout<<itr.first<<" "<<itr.second<<endl; } return 0; } |
Output:
4 Section
1 Name
2 Age
Notice the order of keys in the output. Since we are using the unordered map, the keys are ordered randomly.
Further reading:
Print Map in C++ by Overloading the ostream Insertion Operator (<<)
The ostream_iterator is an output iterator. It can write the content of a container to an output stream.
You can overload the insertion operator (<<) of this class to print the map in C++. This function is defined in the iterator
header file.
- The overloading operator accepts a map of generic type (or the type of your map).
- It then writes the content of the map to a stream by looping through the map.
- Note that the code uses a pair to store each data point of the map. This is because of the fact that maps store data as key-value pairs.
- Finally, it returns the stream. At this point, the stream has all the data of the map written to it.
Let us see the code to print the content of the map using this method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#include <iostream> #include <map> #include <iostream> #include <map> #include <unordered_map> #include <iterator> using namespace std; template <typename key, typename value> ostream &operator<<(ostream &stream, const map<key, value> &myMap) { for(const pair<key, value> &t: myMap) { stream << t.first<<" "<<t.second<<" "<<endl; } return stream; } int main() { map<int, string> mp; mp.insert(make_pair(1, "Name")); mp.insert(make_pair(2, "Age")); mp.insert(make_pair(4, "Section")); mp.insert(make_pair(3, "Class")); cout<<mp; return 0; } |
Note that the code uses the ‘template’ that allows the function to take any generic data type values.
Do not forget the const
keyword otherwise the code with throw a compilation error.
Output:
2 Age
3 Class
4 Section
Print Map in C++17 Using Structure Binding and Range-Based for Loop
C++17 facilitates using the range-based for loops with structure binding. It means you can further cut the clutter and simply define the data holding variables as the loop variables.
Let us see the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <iostream> #include <map> using namespace std; int main() { map<int, string> mp; mp.insert(make_pair(1, "Name")); mp.insert(make_pair(2, "Age")); mp.insert(make_pair(4, "Section")); mp.insert(make_pair(3, "Class")); for(const auto &[key, value]: mp) { cout<<key<<" "<<value<<endl; } return 0; } |
Output:
2 Age
3 Class
4 Section
Print Map in C++17 Using for_each() Function
The for_each()
function applies a pre-defined function to all the data values in the given range. To use this function you must include the algorithm
header file in your code.
The definition of the for_each()
is given below.
1 2 3 4 |
template <class InputIterator, class Function> Function for_each (InputIterator first, InputIterator last, Function fn); |
Note that you must define a function that takes a key-value pair and prints it. You can then pass the starting and ending iterators along with your custom function to for_each()
.
- The custom function takes a pair from the map as an argument.
- It prints the
first
(key) andsecond
(value) data from the pair.
Let us see the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#include <iostream> #include <map> #include <algorithm> using namespace std; void fun(const pair<int, string> &myPair) { cout<<myPair.first<<" "<<myPair.second<<endl; } int main() { map<int, string> mp; mp.insert(make_pair(1, "Name")); mp.insert(make_pair(2, "Age")); mp.insert(make_pair(4, "Section")); mp.insert(make_pair(3, "Class")); for_each(mp.begin(), mp.end(), fun); return 0; } |
Warning: Do not forget the const
keyword in the fun
function. Omitting it will result in a compilation error.
Output:
2 Age
3 Class
4 Section
Conclusion
When it comes to printing the data of a map, the unordered map behaves similarly to the map. Thus you can the method interchangeably for both types of maps.
This is all about how to print Map in C++.
Hope you have enjoyed reading the article. Stay tuned for more such articles. Happy learning!
References
- https://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/
- https://www.cplusplus.com/reference/algorithm/for_each/